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);
}
首先,这会将标记对象添加到标记列表中。然后该标记对象将“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
答案 0 :(得分:1)
向产品添加标签对我来说更有意义。我不允许将产品添加到标签中。
通过多对多关系,您需要确定哪个实体是关系中的主要实体,并通过它控制对集合的访问。您可以通过将另一个实体上的Add方法标记为内部来控制访问。
标记实体:
internal virtual void AddProduct(Product product)
{
this.Products.Add(product);
}
答案 1 :(得分:0)
不要使用MTM关系man,而应该创建一个只有2列的新表Products_Tags:ProductID和TagID。这两个外键都是这样的:
Users
/ \
/ \
M-T-O M-T-O
/ \
/ \
Products Tags
\ /
\ /
\ /
\ /
\Products_Tags/
答案 2 :(得分:0)
检查列表是否已包含此元素是一种很好的做法。
if ( !this.Tags.Contains(tag) )
{
this.Tags.Add(tag);
product.AddTag(this);
}
答案 3 :(得分:0)
Tag.AddProduct应仅添加到代码的内部产品列表中,而Product.AddTag应仅添加到产品的内部代码列表中。持久化到DB应该处理交叉映射 - 当您保存每个产品时,映射表应该在映射表中保存一行,并且当您保存每个标记时相同。
在域中维护这个逻辑对我来说没有意义,我也看不到任何真正的好处。产品有许多标签,标签有很多产品 - 这应该是域的结构,持久层负责多对多关系。
这样,对于任何你知道它有什么标签的产品,反之亦然,这是你真正需要知道的。
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);
}