EF 数据库优先映射混乱

5
我遇到了EF的一个令人沮丧的情况。这是一个行为的简单演示。首先是数据库架构:
如您所见,“RestrictedProduct”是产品的特殊情况,我打算将其作为“Product”的子类,并添加一些特殊代码。
现在我导入了EF数据模型:
糟糕!EF发现“RestrictedProduct”只有2个字段,都是FK,因此将其映射为“Product”和“Restriction”之间的一对多关系。所以我回到数据库并向“RestrictedProduct”添加一个“Dummy”字段,现在我的EF模型看起来好多了:
但是那个“Dummy”字段是愚蠢和无意义的。也许我可以删除它?我从DB表格和实体模型中删除了该字段,然后从DB刷新了模型...
哦,不!“Product-Restriction”关联又回来了,换了一个新名称(“RestrictedProduct1”)!而且无法编译:
是否有办法防止这种行为,而不需要在“RestrictedProduct”表上保留“Dummy”字段?

1
尝试换个方式,创建类模型并查看EF Code First在数据库中创建了哪些表。 - Wim
@Wim - 好主意!我尝试了一下,生成的数据库模型基本上与我开始使用的那个相同。但是从数据库中刷新不会破坏EF模型!我没有看到EDMX文件中底层XML之间的明显区别,但其中有很多技术术语,我确信其中必定有某个秘密开关。你有什么想法吗? - Shaul Behr
抱歉,我们无法帮助您解决这个问题。如果您找到了解决方案,请告诉我们。 - Wim
@Shaul听起来你在这里有一个相当领域驱动设计。你确定DB first是适合你的正确方法吗?我认为edmx生成器不可定制,无法让你关闭一些关联的识别。 - user1914530
@bmewsing 我的印象是DB-first和code-first基本上是可以互换的,因为无论哪种方法,你应该得到几乎相同的结果。我错了吗? - Shaul Behr
@Shaul 我认为它们总体上是一致的,我只是想说你似乎有一个强大的概念模型,所以你最好专注于编码,让 EF 来处理数据库架构。但你可能更喜欢 DB first,我知道我喜欢自己设计模式。我找不到定制生成器的方法,但它只是一个添加生成器,即它不会删除您对模型所做的任何更改,因此您可以每次“从数据库更新模型”时删除不需要的关联,但我同意这很烦人。 - user1914530
2个回答

2

我刚刚遇到了同样的问题,作为一种替代方案,可以将RestrictedProduct表中的虚拟字段放置在其中,以强制创建实体,也可以使RestrictedProduct.RestrictionId字段可为空,EF会生成一个实体。然后,您可以修改它以使用继承,任何后续的“从数据库更新模型”都不会导致不需要的nav属性。这不是一个很好的解决方案,但这是一种变通方法。


就像你所说的,这并不理想,因为从概念上讲它确实是不可空的,但也不比虚拟字段差,所以还是加一分吧... - Shaul Behr

1
让我们缓慢地进入你的问题。
你需要决定的第一件事是,受限制的产品是否真的是产品的特殊情况,还是每个产品的可能扩展。
从你的原始数据库方案中看,任何产品都可以与单个限制相关联,但单个限制可以被多个产品共享。因此,这是一个简单的一对多的情况,这意味着受限制的产品不是产品的特殊情况!限制是一个独立的实体,与产品没有特定的关系。
因此,EF在方案的第一次导入中是正确的: 1. 产品可以具有0或1个限制。 2. 限制是另一个实体,可以与多个产品相关联。
我没有看到你的问题。

谢谢您的回答!我明白您为什么会问那个问题,但是我想要转移话题。我提供的案例并不是我的实际架构,但是解释我的系统中的业务规则需要太长时间,而且这已经不是重点了。让我们假设RestrictedProduct确实是一种特殊类型的Product,具有不同的业务规则,并且该类代码将覆盖Product中的某些虚拟方法。 - Shaul Behr
补充我之前的评论:想象一下,你还有其他的 Product 子类,它们也有不同的业务规则。对于那些只有一个额外字段(比如 RestrictionID)的子类,把它们生成为关系是行不通的;而对于那些有多个字段的子类,则应该生成它们自己的类。 - Shaul Behr
RestrictedProduct如何成为Product的子类?它带来了什么?你遇到的问题与面向对象设计有关,而不是EF。如果我们看经典的动物园例子:你有一个“Animal”类和一个“Visitor”类,你试图说,由于某些动物可以被参观,它们需要成为子类...这是错误的!你可以在你的动物类上有一个IsBeingVisited属性-这将是正确的方法。你需要区分何时应该使用子类,何时只是另一个属性,作为基本规则,问一下它是否添加了什么。 - G.Y
我已经经历了那个过程。我理解子类和属性之间的区别。请认为确实存在一个真正的业务需求来拥有一个子类。 - Shaul Behr
好的,那么你需要将产品设置为限制类的基类,并消除限制类与受限制产品之间的关联。但我觉得这样做可能不再直观了 :) - G.Y

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接