每个实体都继承一个基实体是个坏主意吗?

问题描述 投票:0回答:4

如果我让每个类都从一个提供keyid的基类中继承,会不会有问题(或者说这是个坏主意)? 在Entity Framework中的代码优先设计中。

class MyObject
{
[Key]
public int Id { get; set; }
}

class Person : MyObject {...}
class Message : MyObject {...}
class Whatever : MyObject {...}

我想这样做是因为经常发生这样的情况,我想让两个类(例如)从某个基类继承,但我不知道该由那个基类负责给出id。

具体的例子,对比一下这个。(实际情况)

class Recipient
{
[Key]
public int RecipientId { get; set; } // I want to avoid this
public string DisplayName { get; set; }
}

class Person : Recipient {...}
class Group : Recipient {...}

为了这个。(我想实现什么)

class MyObject
{
[Key]
public int Id { get; set; }
}

class Recipient : MyObject
{
public string DisplayName { get; set; }
}

class Person : Recipient {...}
class Group : Recipient {...}
entity-framework inheritance primary-key
4个回答
3
投票

我知道这个问题已经有一段时间没有人问了,我还是要发个答案。

我已经做了更多的代码优先项目,我现在可以计算,我 始终 最终为我的实体建立了一个抽象的基类。原因很简单,总有一些你认为应该出现在所有实体中的字段。身份证 当然是最明显的。

另外,当你添加了一个基类(或接口),你突然允许你的DbContext在这个抽象上操作。我几乎总是在这个基类中添加事件(比如OnLoad, OnSave, OnDelete),我将这些事件留为虚拟的,然后重写了 保存更改 方法,并为我的DbContext调用相应的受影响实体的事件。

所以我的答案是否定的,在你的EF类中添加一个基类是没有坏处的。但是就像上面的一些答案所说的那样,如果它仅仅是为了Id列,那么也许你还不如在你所有的类中重复那一行(4个基本注释;)。


2
投票

我对此有不同的感受。

  • 它包含了DRY原则(不要重复自己)。

缺点

  • 它违反了继承的目的,即表达 "是一个 "的关系(一个客户 "是一个 "Person)。说一个Person "是一个 "基础对象在业务领域是没有意义的。它没有表达任何业务逻辑。最终,拥有一个基类型可能会阻止其他继承策略,因为C#不支持多重继承。
  • 它混合了业务逻辑和DAL实现。基类中的字段对业务域没有影响。拥有一个 Id 是纯粹的DAL的事情。(价值观也是如此,比如 InsertDateTime 基类型经常使用的)。)

我倾向于 这样做。如果你想让你的实体有共同的东西,我会用一个接口。我知道,这是相当多的工作。而且它看起来并不DRY,但我认为DRY原则应该被定义为 "don't 无谓 重复自己"。

如果尽管如此,你还是决定使用一个基类,我发现确保它不会成为实体模型(实体框架已知的模型)的一部分是有益的。如果会的话,你必须确保EF使用TPC,而且不可能使用其他继承模型。所以,只映射派生类型,EF永远不会知道基础类型,也不会尝试实现和继承策略。


1
投票

我的问题是 why 你会想这样做... ...

I don't see any real reasons to want to 'decouple' base class for the sake of 'ID-ing' alone. 你所节省的只是一行代码。否则,你不会在查询中使用该类(因为它实际上什么都不代表),但你仍然必须小心 "继承"--因为你的代码,与TPC方案将导致额外的表(为所有 "非抽象 "类)--所以我可能会使它成为 abstract 只是为了确定。也不要把它定义为 DbSet (这应该使它 "不被雷达 "发现,就像接口一样)。

如果你已经有了另一个基类--那似乎是 "ID "的理想位置--但这一切都很私人化。

...简而言之 I haven't seen any major issues with it (just make it abstract and off DbSet) - 虽说 equally I don't see any gains from it. 我认为实体POCO是C#对象--但毕竟呈现了一些有意义的底层数据--我喜欢看到它们这样(也适用于任何其他类,而不仅仅是entitiyPOCO)。


0
投票

例如,你想引用userId,但是由于超级类的存在,所有的表都有id。

@AttributeOverrides(value = { @AttributeOverride(name = "id", column = @Column(name = "passwordTokenId", nullable = false)), @AttributeOverride(name = "name", column = @Column(name = "token", nullable = false))})

在hibernate中尝试映射关系......你开始怀疑这个id是类Book还是类Person的

但当你的类被定义为如下时,它是很好的。

公共类 Client 扩展到 Person 公共类 Broker 扩展到 Person

和类Person的定义是有String firstName和String lastName.同样是DRY原则。

我尝试了这两种,我喜欢保持它的简单(KISS).就像上面的先生说,它拥抱DRY,但它也违反(KISS).我同意最后一位先生,我喜欢你喜欢的:),所以遵循你的直觉。

© www.soinside.com 2019 - 2024. All rights reserved.