使用RavenDB在父文档中存储id列表的更简单方法

时间:2013-02-06 18:39:51

标签: ravendb

如果我有一个可以有多个子文件的父文档,例如Store可以有多个Product,那么有更简单的方法可以在{{Product.Id中存储Store列表1}}文件?

目前我只是首先存储Product个对象,然后循环遍历它们以获取Product.Id属性的Store.ProductIds

商品

class Store
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IList<string> ProductIds { get; set; }
    [JsonIgnore]        
    public IList<Product> Products { get; set; }
}

产品

class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
}

当前工作保存方法

var store = new Store()
{
     Name = "Walmart",
     Products = new List<Product>
                    {
                        new Product {Name = "Ball"},
                        new Product {Name = "Bat"}
                    }
};

using (var session = DocumentStore.OpenSession())
{
    foreach (var product in store.Products)
    {
        session.Store(product);
    }

    session.SaveChanges();

    var list = new List<string>();

    foreach (var product in store.Products)
    {
        list.Add(product.Id);
    }

    store.ProductIds = list;

    session.Store(store);
    session.SaveChanges();
}

1 个答案:

答案 0 :(得分:2)

要回答您的具体问题 - 您可以使用代码简化两件事:

  • 您可以删除第一个session.SaveChanges();当您在产品上调用.Store()时,系统会创建产品ID。

  • 您可以使用某些linq收集产品ID以将其折叠为一行:

    store.ProductIds = store.Products.Select(x=> x.Id).ToList();

你仍然有相同的通用方法 - 它只是简化了一些代码。

此方法将工作,但确实意识到您只是为了方便而将产品放入商店。 [JsonIgnore]在这里可以,但它只对序列化有帮助 - 而不是反序列化。换句话说,在加载商店时,只会填充ProductIds列表。您必须单独加载它们(可能使用.Include()

就个人而言,我会将Products列表完全从Store对象中取出。其他关系产品如Entity Framework和NHibernate为此目的使用虚拟成员和代理类,但它在RavenDB中没什么意义。您班级的消费者不会知道该属性被忽略,因此他们可能会误解其用法。当我看到Products属性时,我的期望是每个Product完全嵌入到文档中 - 在这种情况下,您不需要单独的ProductIds列表。让他们两个被忽略只会导致混乱。

针对您提出的设计的另一个论点是,它隐含地使每个商店中的每件商品都独一无二。这是因为您正在使用商店创建产品,然后单独添加每个产品。如果确实所有产品都是独一无二的(不仅仅是“球”,而是“这个特定的球”),那么您可以在没有[JsonIgnore]ProductIds列表的情况下嵌入产品,并且Product不需要作为单独的文件存在。在更可能的情况下,产品不是唯一的(多个商店可以销售蝙蝠和球),那么你有两个选择:

class Store
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IList<string> ProductIds { get; set; }
}

class Store
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IList<Product> Products { get; set; }
}

Product在任何一种情况下都会出现在自己的文档中 - 第二种情况将用作denormalized reference,这样您就可以在不加载产品的情况下获取产品名称。这是可以接受的,但如果产品名称可以更改,那么您需要进行大量修补。

对不起,如果没有干净的“这样做”答案。 Raven有很多选择,有时这种或那种方式更好,取决于你可能使用它的所有不同方式。我个人 - 我会保留ProductIds列表。您始终可以index the related document提取产品名称以进行查询。