【问题标题】:A key cannot be configured on 'FooEntity' because it is a derived type. The key must be configured on the root type 'Foo'无法在“FooEntity”上配置键,因为它是派生类型。必须在根类型“Foo”上配置密钥
【发布时间】:2020-09-23 00:36:21
【问题描述】:

我有一个基类Foo,其中包含我在我的应用程序中需要的所有属性。 ui 使用具有必要 ui 属性的派生类 (FooUi)。例如,数据库使用具有Id 属性的派生类 (FooEntity)。但这似乎是问题的症结所在,因为根据例外情况,这在EF core 中可能是不允许的。这里是否有一个优雅的解决方案,这样我就不必在我的基类中打包 Id 属性,因为我在其他任何地方都不需要它并且仍然有可能拥有密钥?

public class Foo
{

}

public class FooEntity : Foo
{
    public int Id { get; set; }
}

public class FooDbContext : DbContext
{
    public DbSet<FooEntity> Foos { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<FooEntity>(builder =>
        {
            builder.ToTable("Foos");

            // here the exception occurs
            builder.HasIndex(entity => entity.Id);
        });

        base.OnModelCreating(modelBuilder);
    }
}

例外

无法在“FooEntity”上配置键,因为它是派生类型。必须在根类型“Foo”上配置密钥。如果您不打算将“Foo”包含在模型中,请确保它不包含在上下文的 DbSet 属性中、在对 ModelBuilder 的配置调用中引用或从包含的类型的导航属性中引用在模型中。

【问题讨论】:

  • 你的目标是什么?为什么需要这样的基类?通常将数据访问模型与其他(尤其是 UI)模型混合是自找麻烦。
  • 我的目标是拥有一个尽可能精简的基类,一方面避免重复代码,另一方面,模型始终相互兼容,因为所有属性都是制服。例如,我不需要 ID,因为它只与数据库相关,而 UI 中不需要。

标签: c# entity-framework entity-framework-core


【解决方案1】:

我之前有answeredquestion 有点相似。

我认为您应该避免混合 UI 模型 (FooUi) 和数据访问模型 (FooEntity) 的主要原因是您违反了 seperation of concerns 设计原则。

正如您所见,Entity Framework 不支持这一点,尽管我认为这主要是出于技术原因,但它也表明您正在尝试做一些您不应该做的事情。你只给出了一个非常简化和假设的例子,所以很难给你一个恰当的例子来说明为什么这是一个坏主意。但是借用我的旧答案(您可以将“域”替换为“ui”):

当您将域模型与数据访问模型混合使用时,您的域逻辑完全取决于您对数据库中的数据进行建模的方式。这很快限制了您的选择,因为数据库可能对您如何建模与您要实现的域逻辑不匹配的数据有一些限制,并且使维护变得困难。例如。如果您决定将一个数据库表拆分为两个,那么您可能面临一项艰巨的任务,以使您的域逻辑与这两个新模型/表一起工作。此外,如果不提前考虑,在您的数据库中进行性能优化很容易成为一场噩梦 - 您不应该在必要之前花时间考虑优化您的系统。

在 cmets 中,您只提到了为什么要这样做的外观原因,例如“避免重复代码”和“我不需要 UI 中的 ID [...]”,与此相比,这是一个非常小的好处不利的一面是使模型之间的依赖关系如此复杂。

你应该怎么做:分别为数据访问(实体模型)和 UI 创建一个模型。在这种情况下(就像您自己的场景一样),您仍然需要一些代码/逻辑来映射两个模型之间的数据。唯一的缺点是你创建了两个看起来相似的类,这真的一点也不费时间。

【讨论】:

  • 非常感谢您的回复!那没有回答我的问题,但是您在separation of concerns 上的提示非常有用!我将相应地修改我的数据模型并在接口上构建一切!
猜你喜欢
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多