gpt4 book ai didi

c# - MongoDB 组合键 : InvalidOperationException: {document}. 不支持身份

转载 作者:IT老高 更新时间:2023-10-28 12:29:27 26 4
gpt4 key购买 nike

我在对包含复合 ID 的类进行补水时遇到问题,该复合 ID 又具有基类,我收到一条错误消息,提示 InvalidOperationException: {document}.Identity is not supported。

我要写入数据库的类如下:

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; }
}

依次有一个 ID Sku,它是由以下复合值(VendorId 中的本地 Value 组成的类) 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};
}
}

我有一个用于我的实体 Identity 的基类,我在我的 DDD 库中使用它,本质上,这里的 ToString() 输出可以用作 ID,如果这样可以简化事情:

public abstract class Identity<T> : IEquatable<Identity<T>>
{
public override bool Equals(object obj) { /* snip */ }
public bool Equals(Identity<T> other) { /* snip */ }
public override int GetHashCode() { /* snip */ }

public override string ToString()
{
var id = string.Empty;

foreach (var component in GetIdentityComponents())
{
if (string.IsNullOrEmpty(id))
id = component.ToString(); // first item, dont add a divider
else
id += "." + component;
}

return id;
}

protected abstract IEnumerable<object> GetIdentityComponents();
}

我在应用启动时注册了映射:

// 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);
});

但是当我去写的时候,我得到 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);

不确定这是否因为我直接从我的实体层坚持而变得过于复杂(或者我是否只使用自动映射器和更简单的 POCO)......或者我是否缺少一些映射指令。

感谢任何帮助或指点。

最佳答案

我正在查看通过 GetProperties 完成的构造函数帖子的水合作用。

所以 public readonly Sku Sku; 不会通过 classMap.ClassType.GetTypeInfo().GetProperties(_bindingFlags) 显示,因为它只能作为成员访问 field 。

您可以将其更改为 public Sku Sku { get; } 因此它通过构造函数通过 GetProperties 进行水合,并更改所有只读字段(Sku - VendorId, Value & VendorId - Value fields) 拥有属性 getter 方法。

另外,您必须添加 cm.MapProperty(c => c.Identity) 以便 x=>x.Identity.Equals(entity.Identity) 可以用作表达式时被序列化,因为 Identity 不能通过 ImmutablePocoConvention 进行水合和注册,因为它不是自动映射逻辑运行时的构造函数 arg。

代码更改:

public class Sku : Identity<Product>
{
public VendorId VendorId { get; }
public string Value { get; }
}

public class VendorId : Identity<Vendor>
{
public string Value { get; }
}

BsonClassMap.RegisterClassMap<Product>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Sku);
cm.MapProperty(c => c.Identity);
});

关于c# - MongoDB 组合键 : InvalidOperationException: {document}. 不支持身份,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45579507/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com