xBimTeam / XbimEssentials

A .NET library to work with data in the IFC format. This is the core component of the Xbim Toolkit
https://xbimteam.github.io/
Other
494 stars 173 forks source link

Problem with queries in the ifc structure at esent database #577

Open DialPawlowski opened 3 weeks ago

DialPawlowski commented 3 weeks ago

Hello.

I have a Problem after the update from Version 5.1.341 to 6.0.445. After the update I had a problem with an ifc file grater 100 MB.

 IfcModel = IfcStore.Open(fileInfo.FullName, null, null, (_, _) => { progressManager.IncrementProgress(); });

Search function no longer returned any results with the ifc database in the esent database.

Here is an example for one search:

ifcStorey.Model.Instances
                          .Where<IIfcRelContainedInSpatialStructure>(relation=> relation.RelatingStructure == ifcStorey)
                          .SelectMany(subrel => subrel.RelatedElements);

The comparison from relation.RelatingStructure and ifcStorey does not work in the new version. At this point, only Equals would work.

If I open the IFC in memory, the queries will work as usual. (ifcDatabaseSizeThreshHold -1)

 IfcModel = IfcStore.Open(fileInfo.FullName, null, -1, (_, _) => { progressManager.IncrementProgress(); });

Is there any Problem with the Esent Database? Looks like querying an object always returns a new instance. Or is it normal that a IfcStorey has a new instance in the IIfcRelContainedInSpatialStructure.RelatingStructure property?

martin1cerny commented 3 weeks ago

Hi @DialPawlowski , thank you for opening this thread. ESENT implementation is trying to be as lightweight as possible, so it doesn't keep references to objects. As a result, the actual object you got earlier and the one you are comparing have identical shape, but are fundamentally different objects with different object reference. At the same time, you use the interface to retrieve the data, but we can't override the equality operators for interfaces to handle this case.

The solution is either to use entity caching of the IModel (using var cache = model.BeginEntityCaching()), or use the object.Equals() function which is overriden to handle this case, or use entity.EntityLabel as a means of object identity, or you can use MemoryModel which keeps the full object graph in memory with all objects being unique. It all depends on your scenario. But I agree this can get very confusing.

DialPawlowski commented 2 weeks ago

Thanks for your response. I tried to use the entity cach using var cache = model.BeginEntityCaching() but this works not for Esent DB. In that case the cache is a DummyCache and the cache is not in use. Is this normal or have I done something wrong?