对象/实体:多对多+多对一
Users / \ / \ M-T-O M-T-O / \ / \ Products----M-T-M----Tags
我想知道是否有任何文档介绍如何使用实体创建类似这样的模式。我被困在想知道哪个实体应该对关系中的内容负责。对象/实体:多对多+多对一
例如:
假设我想为产品添加标签。我在我的
产品实体像这样的方法:
public virtual void AddTag(Tag tag)
{
this.Tags.Add(tag); // IList<Tag> Tags
tag.AddProduct(this);
}
首先这增加了一个标签对象的标签列表。然后,该标签对象将“这个”产品添加到它自己的产品列表中。
到目前为止这么好。
但是,如果我想要将产品添加到标签,该怎么办。我在我的
标签实体像这样的方法:
public virtual void AddProduct(Product product)
{
this.Products.Add(product); // IList<Product> Products
// product.AddTag(this);
}
首先,我的产品对象添加到产品列表中我的标签对象。然后,我可以将“this”标签添加到产品中,但这是我卡住的地方。被评论的方法会抛出一个stackoverflow错误,因为它会调用AddProduct来调用AddTag,等等。
不确定我的模式是否真的正确。从用户到标签的M-T-O可以让我们轻松查看用户拥有的标签。
所以我想知道是否有人能指引我进入正确的方向?
由于提前,
Pickels
对我来说,添加标签到产品上更有意义。我不会允许产品添加到标签。
通过多对多关系,您需要决定哪个实体是关系中的主要实体,并通过它控制对集合的访问。您可以通过将另一个实体的Add方法标记为内部来控制访问。
标签实体:
internal virtual void AddProduct(Product product)
{
this.Products.Add(product);
}
不要使用MTM关系的人,而不是这个,你应该创建只有2列的新表Products_Tags:产品ID和标签识别。这两个外键是这样的:
Users
/ \
/ \
M-T-O M-T-O
/ \
/ \
Products Tags
\ /
\ /
\ /
\ /
\Products_Tags/
这是一个很好的做法,以检查是否已经列表包含此元素。
if (!this.Tags.Contains(tag))
{
this.Tags.Add(tag);
product.AddTag(this);
}
Tag.AddProduct应该只添加到标签内部的产品清单,并Product.AddTag应该只添加到产品内部的标签列表。持久化到数据库应该处理交叉映射 - 当你保存每个产品时,映射表应该有一个保存在映射表中的行,并且当你保存每个标签时都是一样的。
在域中维护这种逻辑对我来说没有意义,我也不能看到任何真正的好处。一个产品有很多标签,一个标签有很多产品 - 这应该是域的结构,持久层负责多对多的关系。
这样,对于任何产品,你知道它有什么标签,反之亦然,这是你真正需要知道的。
class Users
{
private Tags tags;
private Products products;
}
class Tags : IList<Tag> {}
class Tag
{
private Products products;
public void AddProduct(Product product);
}
class Products : IList<Product> {}
class Product
{
private Tags tags;
public void AddTag(Tag tag);
}
我对此非常不满,保持关系的双方保持内存中的对象一致。遵循这一逻辑,您必须坚持并检索您的产品和标记对象以使其集合包含预期的对象。 – 2010-01-29 17:17:56
但是肯定依赖于系统的体系结构,因为内存中的对象可能与给定M2M关系的数据库不同步,所以负载可能会谨慎以避免假设内存中状态与数据库的内存状态相匹配? – 2010-01-31 01:47:27
我认为他们低估了你,因为我谈论的是实体而不是任何数据库模式。在我的数据库中,我将有一个ProductsTags表。 – Pickels 2010-01-29 16:11:52
问题是如何建模域模型中的多对多关系,而不是数据库中。 – 2010-01-29 16:13:04