关于在使用Entity框架时将业务逻辑放在何处的困惑

时间:2013-01-15 17:56:31

标签: c# entity-framework

我刚刚开始使用Entity框架,我对业务层中正常的类如何适应实体框架创建的实体感到困惑。

当使用经典的ADO.NET时,我会有一个名为Customer的类,然后是另一个名为DALCustomer的类来处理数据库交互,在这个结构中我会把代码放到计算,过滤和delcare实例中DAL与客户一起在Customer类中保存,更新和删除。

使用Entity Framework,如果您有一个名为Customer的表,Entity框架会创建一个名为Customer的实体,这就是我的困惑开始的地方,这个实体是否消除了业务层中对Customer的需求?因此,实质上通常在业务层中的所有字段和方法都在实体框架生成的实体中?或者,如果一个类仍然存在于名为CustomerBL的业务层中,它仍然包含完成计算,过滤所需的业务逻辑所需的字段和方法,并且仍然需要声明处理数据访问的EF DAL实例?

如果应该有一个业务类,在这种情况下是CustomerBL,另一个问题是,如果客户实体中创建的字段在CustomerBL中重新创建,或者应该在CustomerBL中声明Customer实体的实例,那么没有必要在2个位置声明字段吗?

4 个答案:

答案 0 :(得分:25)

与linq-to-sql相反,实体框架的设计考虑了数据模型和概念模型之间的分离。它支持inheritanceentity splittingtable splittingcomplex typestransparent many-to-many associations,所有这些都可以根据需要模拟域模型,而不会受到太多限制数据存储模型。

代码优先方法允许使用POCO,其中所选属性可以映射到数据存储列。模型优先和数据库优先生成部分类,允许人们扩展生成的代码。与这些课程合作在很大程度上具有与POCO合作的外观和感觉。从版本5开始,当DbContext成为默认API时,生成的类不再填充ObjectContext API的与持久性相关的代码。

当然,概念模型和商店模型的这种分离只能在一定程度上取得成功。有些事情违背了持久性无知的目标。例如,如果需要延迟加载,则必须将导航属性声明为virtual,因此EF可以在代理类型中覆盖它们。并且非常方便的是具有伴随“真实”关联(ParentId引用)的原始外键属性(例如,Parent)。纯粹主义者认为这违反了域驱动设计。

持久性无知的另一个重要违规是大量的differences between linq-to-objects and linq-to-entities。你不能忽视这样一个事实:你正在与一个完全不同的宇宙而不是内存中的物体。这被称为tight coupling, or leaky abstraction

但是......一般来说,我很高兴将代码优先模型中生成的EF类或POCO用作域类。到目前为止,我从未见过从一个数据存储到另一个数据存储的无摩擦过渡,如果它发生的话。坚持无知是一种虚构。来自DAL的特性总是在该领域留下足迹。只有当您需要为不同的数据存储/模型编写代码或者预计存储/模型会相对频繁地更改时,才能尽可能地减少这种占用空间或完全抽象出来。

另一个因素是可以将EF类提升为域类,因为今天许多应用程序都有多层,其中(序列化)不同的视图模型或DTO被发送到客户端。在UI中使用域类几乎不符合要求。您也可以将EF类用作域,并让服务根据UI或服务使用者的要求丢弃专用模型和DTO。如果只是表现,那么另一个抽象层可能更多的是负担而不是祝福。

答案 1 :(得分:13)

在我看来,使用POCO作为可以持久化的实体的重点是消除“数据库实体”和“业务实体”之间的区别。 “实体”应该是“业务实体”,可以直接存储到数据存储并从数据存储加载,因此可以同时充当“数据库实体”。通过使用POCO,业务实体与特定机制分离,以与数据库进行交互。

您可以将实体移动到一个单独的项目中 - 例如 - 没有对任何EF程序集的引用,但在数据库层项目中使用它们来管理持久性。

这并不意味着您可以完全设计您的业务实体而不考虑EF的要求。当您使用EF将业务实体映射到数据库模式时,您需要了解一些限制以避免麻烦,例如:

  • 您必须创建导航属性(引用或引用其他实体的集合)virtual以支持使用EF延迟加载
  • 您不能将IEnumerable<T>用于必须保留的集合。它必须是ICollection<T>或更多派生类型。
  • 坚持private属性
  • 并不容易
  • EF不支持char类型,如果要保留其值,则无法使用
  • 以及......

但是在我看来,另外一组实体是一个额外的复杂层,如果上述限制对你的项目而言太紧,那么这些复杂性应该是真正需要的。

YA2C(还有2美分:))

答案 2 :(得分:2)

这个话题可能有点旧,但这可能会有所帮助。 Andras Nemes在他的博客中指出了使用DDD(域驱动设计)而不是EF,MVC等技术驱动设计的关注。

http://dotnetcodr.com/2013/09/12/a-model-net-web-service-based-on-domain-driven-design-part-1-introduction/

答案 3 :(得分:0)

我使用业务逻辑编写我的方法,并在其创建的视图中返回结果,如:

namespace Template.BusinessLogic
{
    public interface IApplicantBusiness
    {
        List<Template.Model.ApplicantView> GetAllApplicants();

        void InsertApplicant(Template.Model.ApplicantView applicant);
    }
}