`ECClass.getDerivedClasses()` doesn't include classes from referenced schemas
Describe the bug
When an iModel / ECDb contains schemas, whose classes are derived from by classes in referencing schemas, calling ECClass.getDerivedClasses() on a base class form referenced schema doesn't return any classes.
To Reproduce
To reproduce the behavior, run this test:
it.only("`ECClass.getDerivedClasses()` doesn't include classes from referenced schemas", async function () {
await IModelHost.startup();
// create a new ECDb
const ecdbPath = "/home/grigas/test.ecdb";
IModelJsFs.unlinkSync(ecdbPath);
const ecdb = new ECDb();
ecdb.createDb(ecdbPath);
// import referenced schema
const schemaXml1 = `
<?xml version="1.0" encoding="UTF-8"?>
<ECSchema schemaName="TestSchema1" alias="Test1" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
<ECEntityClass typeName="X" />
</ECSchema>
`;
const schemaFilePath1 = "/home/grigas/test_schema1.xml";
fs.writeFileSync(schemaFilePath1, schemaXml1);
ecdb.importSchema(schemaFilePath1);
ecdb.saveChanges();
// import referencing schema
const schemaXml2 = `
<?xml version="1.0" encoding="UTF-8"?>
<ECSchema schemaName="TestSchema2" alias="Test2" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
<ECSchemaReference name="TestSchema1" version="01.00.00" alias="test1" />
<ECEntityClass typeName="Y">
<BaseClass>test1:X</BaseClass>
</ECEntityClass>
</ECSchema>
`;
const schemaFilePath2 = "/home/grigas/test_schema1.xml";
fs.writeFileSync(schemaFilePath2, schemaXml2);
ecdb.importSchema(schemaFilePath2);
ecdb.saveChanges();
// set up schema locater
const locater = new SchemaJsonLocater((name) => ecdb.getSchemaProps(name));
const context = new SchemaContext();
context.addLocater(locater);
const testSchema1 = await context.getSchema(new SchemaKey("TestSchema1"), SchemaMatchType.Latest);
const classX = await testSchema1!.getItem("X", EntityClass);
const derivedClasses = await classX!.getDerivedClasses();
expect(derivedClasses!.length).to.equal(1);
await IModelHost.shutdown();
});
Expected behavior
- Calling
ECClass.getDerivedClasses()on a base class, returns all its derived classes, including ones from referencing schemas. - The test passes.
Desktop (please complete the applicable information):
- OS: Ubuntu
- Node.js version
20.18.2 - iTwin.js version
5.0.0-dev.92
Additional context
I understand it might be problematic to get derived classes from referencing schemas, if those schemas haven't been loaded. If fixing this is not possible, the situation should be clearly explained on affected methods (I suspect that might be more than just getDerivedClasses()), and, ideally, a recommendation on how to get those derived classes should be provided.
@ColinKerr what do you think about this? My opinion is that loading derived schemas is not a good idea as that basically translates into "try and load every single schema you can find".
Maybe we can provide some specialized method which does just that, but limiting the schemas loaded to the ones inside of the imodel?
Other than that I'd say like Grigas suggests, we should document the limitation
With incremental loading of Stub classes I think it is fine if we support this. @christophermlawson, @StefanApfel-Bentley @AureMonke please investigate this
The problem is derived classes are not a part of the schema. The 'base' schema (TestSchema1) contains no references so the API has no way to know to look for schemas that reference it. If you load both schemas before the getDerivedClasses call, then the correct results are returned. We need to discuss how to support what Grigas is trying to do. As things currently stand, loading all pertinent schemas first resolves the issue. Incremental loading will not address this problem. Derived classes is the only outlier here. All other metadata information is contained withing the schema. I can add documentation to this method to describe this limitation.
For the incremental Schema Loading, I could imagine we can query that information on the class stubs and construct the tree internally, even if the items not fully loaded yet. I'd like to do some deeper investigation here, since that would be another complex query on the time sensitive stubs query.
https://github.com/iTwin/itwinjs-core/pull/8795. Hey, I created a PR fixing this issue. Please let me know if I missed anything.