Elfocrash / Cosmonaut

🌐 A supercharged Azure CosmosDB .NET SDK with ORM support
https://cosmonaut.readthedocs.io
MIT License
342 stars 44 forks source link

Polymorphic Store type #119

Closed rhalaly closed 4 years ago

rhalaly commented 4 years ago

I tried to create a "Polymorphic Store" that will return multiple types in one query. For example:

class Foo {}
class Bar : Foo {}
class Baz : Foo {}

And I want to get in one query all the Bar & Baz classes in one query. They both stored in a shared collection.

Doing such thing:

var store = new CosmosStore<Foo>(client, "DB", "Foos");
return await store.Query().Where(...).ToListAsync();

will return empty result, since cosmonaut adds CosmosEntityName == 'foo'.

If I disable the "IsShared" property with reflection:

var store = new CosmosStore<Foo>(client, "DB", "Foos");
typeof(CosmosStore<Foo>).GetProperty("IsShared").SetValue(store, false);
return await store.Query().Where(...).ToListAsync();

will return ALL the Foos classes, but it will not fill the properties that are defined in Bar and Baz classes, but only the Foo (base class) properties.

So I didn't found any way to receive Bar & Baz in one query. Does Cosmonaut support it?

badreddine-dlaila commented 4 years ago

did you found any solution for this ?

badreddine-dlaila commented 4 years ago

Ok got it 😁 For the records: I used JsonSubTypes (https://github.com/manuc66/JsonSubTypes#serializeobject-and-deserializeobject-with-custom-type-property-only-present-in-json)

public class ParentClass { }

[SharedCosmosCollection("Store", "ClassA")]
public class ChildClassA : ISharedCosmosEntity
{ 
  ...
public string CosmosEntityName { get; set; }
}

[SharedCosmosCollection("Store", "ClassB")]
public class ChildClassB : ISharedCosmosEntity
{ 
  ...
public string CosmosEntityName { get; set; }
}
 var jsonSerializerSettings = new JsonSerializerSettings
 jsonSerializerSettings.Converters.Add(
       JsonSubtypesConverterBuilder
           .Of(typeof(ParentClass), "CosmosEntityName")
           .RegisterSubtype(typeof(ChildClassA), "ClassA")
           .RegisterSubtype(typeof(ChildClassB), "ClassB")
           .SerializeDiscriminatorProperty()
           .Build()
);