在 RavenDb 中存储对象时出现以下错误
我只为存储的对象分配一个键,我使用重载的 store 方法来存储实体。
Store 只被调用一次,所以为什么会抛出这样的异常。我不明白有关对象标识的一些内容。
除了 ravendb 持久性之外,Id
属性还有另一个用途。
实体 UserQuery+MyItem 具有文档键“mykeypath/44”,但现在具有文档键属性“MyItems/44”。您无法更改加载到 session 中的实体的文档键属性
。
编辑以包含完整的源代码
void Main()
{
var host = "http://myhost:8020";
var _documentStore = new DocumentStore { Url = host, DefaultDatabase = "sdb" };
_documentStore.Initialize();
using (var session = _documentStore.OpenSession())
{
var path = "mykeypath/44";
session.Store(new MyItem { Id = 303, Test = "TEST" }, path);
session.SaveChanges();
}
}
public class MyItem : AuditableEntity {
public string Test { get; set; }
}
[Serializable]
public abstract class AuditableEntity : IAuditable
{
[DataMember]
[Display(Name = "Id", Description = "Id")]
public long Id { get; set; }
[DataMember]
[Display(Name = "Modified By", Description = "Modified By")]
public string ModifiedBy { get; set; }
[DataMember]
[Display(Name = "Modified Date", Description = "Modified Date")]
public DateTime ModifiedDate { get; set; }
}
最佳答案
如果您的类有一个名为 Id
的属性,RavenDB 默认情况下将使用它作为文档 ID。
在您的情况下,将 MyItem
实例的 Id
设置为 303
意味着该文档将保存在数据库中ID 为 MyItems/303
。
您可以通过修改来轻松测试
session.Store(new MyItem { Id = 303, Test = "TEST" }, path);
与
一致session.Store(new MyItem { Id = 303, Test = "TEST" });
这将会起作用,结果将是:
所以,问题是您指示 Raven 为您的对象分配两个 ID:
MyItems/303
,由于Id
属性的值mykeypath/44
,因为您通过使用Store
重载显式设置此 Id。
在这种情况下我要应用的解决方案是重命名 Id
属性。如果这是不可能的(例如:该类已用于其他目的,例如 WCF 合约),请考虑创建一个仅用于 RavenDB 持久性的新类,并在两者之间进行映射(像 AutoMapper 这样的工具使这变得容易)。
更新
我通过查看 this thread 找到了一种改变 Id
字段约定的方法。 。
对于您的情况,您应该在打开 session 之前执行以下操作:
_documentStore.Conventions.FindIdentityProperty =
prop =>
{
if (prop.DeclaringType == typeof (AuditableEntity))
return prop.Name == "CustomId";
return prop.Name == "Id";
};
这意味着由 AuditableEntity
类型定义的属性 Id
不应该用作文档标识符。在所有其他情况下,请执行默认设置。
我测试了它,它工作正常,在 RavenDb 工作室中显示了两个 Id 字段:) :
关于c# - 在 SaveChanges 上存储带有 raven db 异常的对象以生成 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18767259/