【问题标题】:Initialization in a Parameterless Constructor (Entity Framework)无参数构造函数中的初始化(实体框架)
【发布时间】:2015-12-15 19:41:28
【问题描述】:

我的问题是:

  1. 是否可以使用 EF 在无参数构造函数中初始化依赖对象?
  2. 如果是这样,执行此操作的正确方法是什么?如果不是,如果不在构造函数中,应该在哪里初始化依赖对象?

在测试我的代码时,我似乎无法在无参数构造函数中初始化对象;如果我这样做,实体框架将无法正确加载它们。

加载对象时,此代码正确加载

abstract public class Channel
{
    public long ID { get; protected set; }
    public Verification Verification { get; protected set; }

    public Channel() { }
}

而这段代码加载不正确

abstract public class Channel
{
    public long ID { get; protected set; }
    public Verification Verification { get; protected set; }

    public Channel()
    {
        Verification = new Verification();
    }
}

注意:在上面的示例中,我正在处理已经存储在数据库中的数据,我没有重新创建数据然后为每个示例加载它(我不知道它有什么不同)。

这是具体的派生类:

public class Email : Channel
{
    public string Address { get; protected set; }

    public Email(string address)
    {
        Address = address;
    }

    public Email() : this(string.Empty) { }
}

为了澄清,这是我创建、保存和加载我的实体的方式:

// Creating / saving
using (Context context = new Context())
{
    Email email = new Email("person@blah.com");
    // Do some stuff with the Verification object

    context.Channels.Add(email);
    context.SaveChanges(); // EF assigns an ID of 1
}

// Loading
using (Context context = new Context())
{
    Email email = context.Find(1); // Using the value of 1 from above
}

当使用上面的“正确加载”构造函数加载时,验证对象被正确加载——它是我创建/保存的那个。当使用“未正确加载”构造函数(具有一些初始化的构造函数)时,验证对象只是一个“新”版本(没有 ID 为 0 的代理)。

我看到的每一页都说无参数构造函数中的对象初始化很好,因为 EF 会正确地将它们识别为未修改的尽管初始化,并用从数据库中提取的值覆盖这些值。我看到的唯一一个说你不能这样做的页面是here,尽管我没有看到任何关于如何在无参数构造函数中初始化对象的建议。

我希望有无参数构造函数,当它们被保证不必创建一个无用的参数化构造函数来绕过 EF 的内部工作。这种“简单”正在杀死我。我使用 EF 越深入,任何面向对象的代码在我眼前恶化得越多。 =*(

【问题讨论】:

  • “无法正常加载”是什么意思?你正在运行什么代码来查看它?
  • @jjjI 我编辑了我的问题以澄清该信息。
  • 只是不要初始化参考导航属性。我想我已经充分证明这有很多不利影响。 EF 类模型不能遵守所有的 OO 原则,它首先是为数据访问量身定制的。
  • @Gert 抱歉,我再次查看了您的问题,但仍然不明白您应该如何初始化对象。假设我想用一个依赖的验证类(与流式 API 建立的关系)创建一个如上所述的“电子邮件”对象。 Verification 对象的初始化应该在什么时候进行?谁对此负责——我还是 EF?当我调用“new Email(...)”时,即使在 SaveChanges() 之后,Verification 对象也是空的,所以我可以看到初始化它的唯一方法是自己做。
  • ...是自己做的。这就是想法。但是让我重新打开这个问题,也许你可以编辑它以更明确地指出何时初始化依赖对象的问题,因为构造函数不是最好的地方。

标签: c# entity-framework constructor initialization


【解决方案1】:

正如my answer you refer to 中所说,在实体框架类模型中,与真正的域模型相反,在实体的构造函数中初始化引用导航属性是一种不好的做法。

但是是的...我们必须在某处初始化参考导航属性。那么最好的地方是什么?我认为信息是:保持简单。我认为应该可以破解 EF 以用它自己实现的对象替换默认对象,但这并非易事。这可能是意外错误的来源。

所以基本上有两种选择:

  • 不要初始化它们,设置原始外键属性:

    var channel = new Channel { VerificationId = someId };
    

    这可能更伤害领域驱动专家的眼睛,但是使用 外键关联(引用和原始属性的组合)是 EF 官方推荐的,因为它有很多优点.

  • 只需在必要时更新它们即可初始化它们。

EF 类模型与域驱动模型仅稍有相似之处。很多 DDD 原则不能应用到它,因为 EF 模型是"just" a data access layer。接受这一点比试图与之抗争要好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多