在SaveChanges上存储具有raven db异常的对象以生成密钥

时间:2013-09-12 14:38:00

标签: c# ravendb

在RavenDb中存储我的对象时出现以下错误 我只为存储对象分配一个键,我使用重载的存储方法来存储实体。
存储只被称为一次所以为什么会抛出这样的异常。我不明白对象身份有什么。

Id属性除了ravendb持久性之外还有其他目的。

Entity UserQuery+MyItem had document key 'mykeypath/44' but now has document key property 'MyItems/44'. You cannot change the document key property of a entity loaded into the 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; }
}

1 个答案:

答案 0 :(得分:3)

如果您的类有一个名为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" });

这将有效,结果将是:

Saved document

因此,问题在于您指示Raven为您的对象分配两个ID:

  • MyItems/303,由于Id属性
  • 的价值
  • mykeypath/44,因为您使用Store重载明确设置此ID。

我在这种情况下应用的解决方案是重命名Id属性。如果那是不可能的(例如:该类已经用于其他目的,如WCF合同),请考虑创建一个仅用于RavenDB持久性的新类,并在两者之间进行映射(像AutoMapper这样的工具使这很简单)。

更新

我找到了一种通过查看this thread来弯曲Id字段约定的方法。 在您的情况下,您应该在开始会话之前执行以下操作:

_documentStore.Conventions.FindIdentityProperty =
    prop =>
        {
            if (prop.DeclaringType == typeof (AuditableEntity))
                return prop.Name == "CustomId";

            return prop.Name == "Id";
        };

这说明类型Id定义的属性AuditableEntity不应用作文档标识符。在所有其他情况下,请执行默认操作。

我测试了它并且工作正常,在RavenDb工作室中显示了两个Id字段:):

enter image description here