从实体类继承并扩展类

Posted

技术标签:

【中文标题】从实体类继承并扩展类【英文标题】:Inheriting from entity classes and extending the class 【发布时间】:2011-06-25 04:28:46 【问题描述】:

我使用 Entity Framework 4.0 来创建我的数据访问层。然后我发现我的业务逻辑层具有与 DAL 相同的对象,但有一些扩展(即更多属性、一些函数和 setter 处的数据验证......)。

我计划在单独的项目中使用 DAL 和 BLL,并正在寻找在 BLL 中使用实体类并防止代码冗余的最佳实践。

我搜索了一下,主要有两个想法:

    通过部分类扩展同一项目内的实体类 使用接口(由实体类和相关BLL类实现)。前者更受程序员欢迎。

上述方案的缺点:

    我们需要在同一个项目中添加代码作为部分类的一部分。这适用于添加属性和方法,但不适用于覆盖某些内容(即在业务逻辑层设置属性之前添加验证) 如果实体模型发生变化,我们需要再次手动从实体类中提取接口,并且还需要对 BLL 相关类进行另一次更改(两次手动解决)。

我的问题是为什么我们不从相关实体类继承我们的 BLL 类并扩展/覆盖它们的方法和属性?

【问题讨论】:

【参考方案1】:

您需要记住的一件事是,ORM 与实体框架类似,实际上并没有创建简单的数据访问层(从一般的 3 层架构来看)。它们为您提供的更多的是一个业务层,对数据访问交互具有更精细的控制级别。我认为可以说 EF 本质上成为你的 DAL,上下文和实体类型可以是 BLL。

当通过更多的 MVC 或 MVVM 架构查看时,这条线更容易看到,其中您有一个模型(您的 EF 层)、一个控制器或视图模型(业务逻辑所在的位置,它封装了模型),并且一个视图。

无论如何,因为 EF 实际上必须直接实例化实体类型,所以继承对您没有多大好处,因为 EF 不会使用您的子类型作为返回的实体。 EF 中验证和类似任务的解决方案是同时使用部分(您显然知道)和部分方法。 EF 中的默认代码生成模板为OnPROPERTYNAMEChangingOnPROPERTYNAMEChanged 的所有标量属性生成部分方法。

例如,如果您的User 实体类型上有一个int UserId 属性,您可以创建一个如下所示的部分类:

public partial class User

    partial void OnUserIdChanging(int newUserId)
    
        // do something
    

    partial void OnUserIdChanged()
    
        // do something
    

当然,如果您愿意,您也可以只使用其中一种。部分方法相对于继承调用的优势(假设它甚至可能)是部分方法是非虚拟的(因此没有虚拟表查找来调用正确的成员)并且是编译的如果有实际实现,则作为类的一部分。

换句话说,即使您可以进入设计器代码并查看声明

partial void OnUserIdChanging(int value);
partial void OnUserIdChanged();

如果您实际上并未将方法体添加到函数中,那么 C# 编译器会从代码中完全删除该函数以及对它的所有调用,就好像它从一开始就从未存在过一样。这使得类型更小,对其他属性的调用更快,因为它不必为调用空函数而烦恼。

【讨论】:

正如你提到的MVC 控制器封装模式的地方,我想在一个单独的项目中封装更高抽象级别的实体类。我仍然可以将新类传递给实体框架,因为继承的类是一种基础实体类。我不会对 EF 生成的代码(实体类)进行任何更改。我需要我自己的BLL 并希望保持 EF 生成的代码不变。我不希望 EF 返回我的子类型。 @Xaqron:关键是 MVC 和类似的架构是通过封装而不是继承工作的。如果您想采用这样的方法,那很好,但是从实体类型本身继承通常不是这样做的。

以上是关于从实体类继承并扩展类的主要内容,如果未能解决你的问题,请参考以下文章

六个视图工具类类

python2学习------基础语法2(类类的继承类成员函数防御式编程)

JS面向对象——class定义类类的构造函数实例方法访问器方法静态方法继承super多态

从扩展 Typegoose 并包含静态类型特定方法的父类继承

面向对象程序设计中啥是类类有几种特性

我可以在休眠中使用单表继承从扩展实体中选择所有超级对象吗?