【问题标题】:Entity Framework Many To Many Relationships initializing ICollection [duplicate]初始化ICollection的实体框架多对多关系[重复]
【发布时间】:2018-10-29 07:39:33
【问题描述】:

例如,假设我们有以下情况:我有一个名为 StandardEngineeredModel 的类,它具有 ModelNumber、VoltageInput、VoltageOutput 等属性。

我还有一个名为 Fuse 的类,它具有诸如 Designator、Rating 和 Type 等属性。在我的数据库模型中,这两个类之间会有多对多的关系,一个 StandardEngineeredModel 可以包含 MANY 个熔断器,一个熔断器可以包含在 MANY 个不同的 StandardEngineeredModels 中。请参阅下面的代码。

public class StandardEngineeredModel
{
    StandardEngineeredModel()
    {
        Fuses = new List<Fuse>();
    }

    [Key]
    public string ModelNumber { get; set; }
    public int VoltageInput { get; set; }
    public string VoltageOutput {get;set;}

    public ICollection<Fuse> Fuses { get; set; }
}

public class Fuse
{
    [Key,Column(Order = 0)]
    public string Designator { get; set; }
    [Key, Column(Order = 1)]
    public string Rating { get; set; }
    [Key, Column(Order = 2)]
    public string Type { get; set; }

    public ICollection<StandardEngineeredModel> StandardEngineeredModels { get; set; }
}

所以我的问题是您在构造函数中初始化集合的部分:对于我的 StandardEngineeredModel,使用列表初始化 Fuse 是有意义的。但是在我的 Fuse 类中,初始化 ICollection 对我来说并没有什么意义,因为通常我会将保险丝分配给 StandardEngineeredModel 而不是将 StandardEngineeredModel 分配给保险丝。

这样做有什么我没有看到的问题吗?这会给我带来哪些类型的问题?我在一些应用程序中使用了 EF,但还需要多对多关系,因此我正在寻找一些关于此的一般性建议。

提前致谢!

【问题讨论】:

  • “但是在我的 Fuse 类中,初始化 ICollection 对我来说并没有什么意义,因为通常我会将熔断器分配给 StandardEngineeredModel 而不是将 StandardEngineeredModel 分配给熔断器。”我想你回答了你自己的问题。您可能不想对了解所有使用它们的设备的保险丝进行建模。但反过来说也有道理——设备知道他们使用什么保险丝是有意义的。
  • 是的,我问的唯一原因是因为在大多数多对多关系的教程中,他们说要初始化关系的双方。我只是想确保我的想法是有道理的哈哈。谢谢! @chadnt
  • 假设这是 EF6(因为您没有提到 EF-core 需要的显式连接类):集合 StandardEngineeredModelsisn't even necessary

标签: c# entity-framework model many-to-many relationship


【解决方案1】:

但在我的 Fuse 类中,初始化 ICollection 对我来说并没有什么意义,因为通常我会将熔断器分配给 StandardEngineeredModel 而不是将 StandardEngineeredModel 分配给熔断器。

你上面说的是真的,但我认为你把这些实体模型领域模型混淆了。在您的域模型中,您的StandardEngineeredModel 中可能有一个方法:

public void AssignFuses(List<Fuse> fuses)

但是在你的Fuse中,你不会有这样的方法:

public void AssignStandardEngineeredModels(
    List<StandardEngineeredModel> sems) // makes no sense

但是,您的域模型客户端(我指的是其他类或开发人员)可能需要从分配给它们的 Fuse 导航到 StandardEngineeredModel,那么它们将如何做呢?那么Fuse 类将需要一个只读的List&lt;StandardEngineeredModel&gt; 来帮助解决这个问题。

现在回到你的实体模型:

这样做有什么我没有看到的问题吗?这会给我带来哪些类型的问题?

如果您有一个包含其他类的类,最好将它们初始化。为什么?因为我们想对自己和其他开发者好。考虑一下:

public class A
{
    public List<string> SomeThings{ get; set; }
    public A(){}
}

我正在使用您的课程,因为我正在使用 DLL,所以我看不到代码。我这样做:

var a = new A();
a.SomeThings.Add("1");

我编译,我将代码提供给 QA,他们忘记测试这个非常具体的案例,然后它进入生产和 BAM !!!

因此,请遵循良好做法并对其进行初始化。我不确定如果你没有初始化 EF 是否会失败,所以也许你可以测试并解决这个问题。

一个建议

我建议不要使用后缀 Model 来命名您的实体模型。如果我的客人是正确的,那么您可能正在为 MVC 执行此操作并认为这是您的模型。但问题是您设计表名的目的是为了在 MVC 中使用它。如果不是呢?此外,在某些情况下,此模型不足以成为 MVC 中的模型,可能需要其他属性。

【讨论】:

  • 两件事:1)这里的主要问题是它将为空,并且会回来咬他(同样,没有延迟加载),以及2)你为什么发布一个答案说@ 987654331@ - 如果你能回答这个问题,你应该知道这是否有效。这个答案具有误导性。
  • @Ben 1) 是的,它会咬他,我提到过。那么如果没有延迟加载呢? 2)因为我给出了许多其他原因,我不确定 EF。他的问题不仅仅是关于 EF。 3)它根本没有误导。我如何误导他/她?
  • 您以某种虚构的方法AssignFuses 开始您的答案,这不是原始问题的一部分,也不是您通过常规做法创建多对多关系的方式。然后,在给出了不好的做法的建议之后,你开始讨论好的做法有多重要。最后,您给出了一个会引发空引用异常的示例,但您没有在帖子中的任何地方解释这一点 - 相反,您谈论的是糟糕的 QA 和生产中的错误。答案很冗长,充满了不相关和误导性的内容。
【解决方案2】:

从技术上讲,您不必在构造函数中初始化集合,但您需要注意它们将为空(尤其是因为您没有使用启用延迟加载的 virtual 关键字)并且您需要检查在整个应用程序中都这样做 - 否则,您可能会在意想不到的地方出现空异常。

【讨论】:

  • 也许 OP 不想延迟加载。这个答案中提供的 2 美分应该只是一个评论。 -1
  • 这篇文章的主要收获是,OP 需要注意集合将为空的事实——我不知道你为什么读到它,只是去掉了关于延迟加载的一点?
猜你喜欢
  • 1970-01-01
  • 2015-07-11
  • 2017-01-28
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多