如何在不同的mongodb集合中存储嵌套对象?

如何在不同的mongodb集合中存储嵌套对象?,mongodb,norm,Mongodb,Norm,我需要存储此类的一些对象: public class Category{ public ObjectId Id {get;set;} public string Name {get;set;} public string Description {get;set;} public List<Product> Products {get;set;} } public class Product{ public ObjectId Id {get;

我需要存储此类的一些对象:

public class Category{
    public ObjectId Id {get;set;}
    public string Name {get;set;}
    public string Description {get;set;}
    public List<Product> Products {get;set;}
}

public class Product{
    public ObjectId Id {get;set;}
    public string Name {get;set;}
    public string Description {get;set;}
    public decimal Price {get;set;}
}

我是否可以将类别和产品对象存储在不同的集合中,并且在类别记录中仅引用一个产品而不更改类代码?(就像NHibernate那样)

不,你不能。至少不是自动的

SQL数据库最适合跨多个表存储规范化的数据。表之间的关系由外键关系定义。NHibernate使用这些外键关系将对象映射到多个表

MongoDB面向存储文档。这些文档通常是数据的非规范化表示。其思想是将相关数据存储在单个文档中,而不是多个表中。因此,MongoDB不需要外键概念,也不需要加入集合

理论上,NoRM将来可以支持这种功能,但这与文档数据库的精神背道而驰。因此,它不太可能得到支持

手动解决方案 通过应用
MongoIgnore
属性,可以告诉NoRM在保存类别时跳过
Products
属性。然后将产品手动存储在单独的集合中,并附上该类别的“参考”。您可以使用自定义集合自动跟踪产品的类别。代码如下所示:

public class ProductCollection : Collection<Product>
{
  private Category owner;

  public ProductCollection(Category owner)
  {
    // Remember who 'owns' the products in this collection.
    this.owner = owner;
  }

  protected override void InsertItem(int index, Product item)
  {
    // Tell the product to which category it belongs.
    item.CategoryId = this.owner.Id;

    base.InsertItem(index, item);
  }

  // Override other methods using the same pattern.
}

public class Category
{
  public Category()
  {
    this.Id = ObjectId.NewObjectId();
    this.Products = new ProductCollection(this);
  }

  public ObjectId Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }

  [MongoIgnore]
  public ProductCollection Products { get; private set; }
}

public class Product
{
  public ObjectId Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }
  public decimal Price { get; set; }
  public ObjectId CategoryId { get; set; }
}
公共类ProductCollection:集合
{
私有类别所有者;
公共产品集合(类别所有者)
{
//记住谁是本系列产品的“所有者”。
this.owner=所有者;
}
受保护的覆盖无效插入项(整数索引,产品项)
{
//告诉产品它属于哪个类别。
item.CategoryId=this.owner.Id;
基本插入项(索引,项目);
}
//使用相同的模式重写其他方法。
}
公共类类别
{
公共类别()
{
this.Id=ObjectId.NewObjectId();
this.Products=新产品集合(this);
}
公共对象Id{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
[蒙哥尼诺]
公共产品集合产品{get;private set;}
}
公共类产品
{
公共对象Id{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
公共十进制价格{get;set;}
public ObjectId CategoryId{get;set;}
}

现在,您可以将类别存储在一个集合中,将产品存储在另一个集合中。
CategoryId
属性将指示产品所属的类别。

产品和类别之间存在一对多关系。我建议您将引用存储在多实体中,就像存储在SQL数据库中一样。因此,产品是指一个类别,而不是相反。其优点是,当您将产品移动到其他类别时,只需更新产品中的引用即可。在您的设计中,您必须将产品从旧类别中删除并添加到新类别中。如果你的例子只是为了说明问题,请忽略我的评论:)谢谢你的完整答案。我将在我的项目中使用此解决方案。
public class ProductCollection : Collection<Product>
{
  private Category owner;

  public ProductCollection(Category owner)
  {
    // Remember who 'owns' the products in this collection.
    this.owner = owner;
  }

  protected override void InsertItem(int index, Product item)
  {
    // Tell the product to which category it belongs.
    item.CategoryId = this.owner.Id;

    base.InsertItem(index, item);
  }

  // Override other methods using the same pattern.
}

public class Category
{
  public Category()
  {
    this.Id = ObjectId.NewObjectId();
    this.Products = new ProductCollection(this);
  }

  public ObjectId Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }

  [MongoIgnore]
  public ProductCollection Products { get; private set; }
}

public class Product
{
  public ObjectId Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }
  public decimal Price { get; set; }
  public ObjectId CategoryId { get; set; }
}