1

如果我有一个可以有多个子级的父文档,例如 aStore可以有多个Products 有没有更简单的方法来存储文档Product.Id中的列表Store

目前我只是Product先存储对象,然后遍历它们以获取Product.IdforStore.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();
}
4

1 回答 1

2

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

  • 您可以消除第一个session.SaveChanges(); 产品 id 将在您调用.Store()产品时创建。

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

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

不过,您仍然有相同的通用方法 - 它只是稍微简化了代码。

这种方法会奏效,但要意识到您只是为了方便而将产品放入商店。 [JsonIgnore]在这里没问题,但它只有助于序列化 - 而不是反序列化。换句话说,在加载商店时,只会填充 ProductIds 列表。您必须单独加载它们(可能使用.Include()

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

反对您提议的设计的另一个论点是,它隐含地使每家商店中的每件产品都独一无二。这是因为您正在使用商店创建产品,然后分别添加每个产品。如果确实是所有产品都是唯一的(不仅仅是“球”,而是“这个特定的球”),那么您可以只嵌入没有[JsonIgnore]orProductIds列表的产品,并且没有必要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无论哪种情况,它仍会在其自己的文档中 - 第二种情况将用作非规范化引用,因此您可以在不加载产品的情况下获取产品名称。这是可以接受的,但如果产品名称可以更改,那么您有很多修补工作要做。

抱歉,如果没有干净的“这样做”答案。Raven 有很多选择,有时一种或另一种效果更好,具体取决于您可能使用它的所有不同方式。我个人 - 我只会保留 ProductIds 的列表。您可以随时索引相关文档以提取产品名称以进行查询。

于 2013-02-06T21:38:34.357 回答