I'm having problems wetting the class, which consists of a composite identifier, which in turn has a base class, I get the error InvalidOperationException: {document}.Identity is not supported.
The class I'm trying to write to the database is given below:
public class Product : IEntity<Product> { public readonly Sku Sku; public string Name { get; private set; } public string Description { get; private set; } public bool IsArchived { get; private set; } public Identity<Product> Identity => Sku; public Product(Sku sku, string name, bool isArchived) { Sku = sku; Name = name; IsArchived = isArchived; } } public interface IEntity<T> { Identity<T> Identity { get; } }
In turn, it has the identifier Sku , which is a class formed from the following composite values ( VendorId and local Value inside Sku ):
public class Sku : Identity<Product> { public readonly VendorId VendorId; public readonly string Value; public Sku(VendorId vendorId, string value) { VendorId = vendorId; Value = value; } protected override IEnumerable<object> GetIdentityComponents() { return new object[] {VendorId, Value}; } } public class VendorId : Identity<Vendor> { public readonly string Value; public VendorId(string value) { Value = value; } protected override IEnumerable<object> GetIdentityComponents() { return new object[] {Value}; } }
I have a base class for my Identity entities that I use in my DDD libraries, essentially the output of ToString () here can be used as an identifier if this simplifies the situation:
public abstract class Identity<T> : IEquatable<Identity<T>> { public override bool Equals(object obj) { } public bool Equals(Identity<T> other) { } public override int GetHashCode() { } public override string ToString() { var id = string.Empty; foreach (var component in GetIdentityComponents()) { if (string.IsNullOrEmpty(id)) id = component.ToString();
I register mappings when the application starts:
// rehydrate readonly properties via matched constructor // https://stackoverflow.com/questions/39604820/serialize-get-only-properties-on-mongodb ConventionRegistry .Register(nameof(ImmutablePocoConvention), new ConventionPack { new ImmutablePocoConvention() }, _ => true); BsonClassMap.RegisterClassMap<Product>(cm => { cm.AutoMap(); cm.MapIdMember(c => c.Sku); }); BsonClassMap.RegisterClassMap<Vendor>(cm => { cm.AutoMap(); cm.MapIdMember(c => c.Id); });
However, when I go and write, I get an InvalidOperationException: {document}.Identity is not supported.
// my respositoru method public void Upsert<T>(T entity) where T : IEntity<T> { this.Database .GetCollection<T>(product.GetType().FullName)() .ReplaceOneAsync(x=>x.Identity.Equals(entity.Identity), entity, new UpdateOptions() {IsUpsert = true}) .Wait(); } var product = new Product(new Sku(new VendorId("dell"), "12434" ),"RAM", false ); myProductRepo.Upsert(product);
Not sure if this is now too complicated for me, persisting right from the level of my entities (or if I just use automapper and simpler POCO) ... or if I miss some matching directives.
Appreciate any help or pointers.