DDD和实体框架类 [英] DDD and Entity Framework classes

查看:61
本文介绍了DDD和实体框架类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了许多有关DDD的文章,并且了解到,我应该在基础架构级别使用域模型类,因此,我应该使用与Entity Framework基础架构相同的类,并使用它们来生成表(代码优先方法)等等.但是我的域模型可以与关系数据库模型完全不同.

I have read many articles about DDD and understood, that I should use my domain model classes in the Infrastructure level, so, I should use the same classes as Entity Framework infrastructure and use them to generate tables (code-first approach) etc. But my domain model can be fully different than Relational DB model.

为什么我不能再创建一个模型,即基础结构模型,来创建关系数据库模型,又不能将域模型与EF类混合使用?

Why I can't create one more model, infrastructure model, to create relational DB model and don't mix domain model with EF classes?

推荐答案

考虑以下简单示例:

域模型

public class Customer
{
    public Customer(IRegistrar registrar)
    {
        this.registrar = registrar;
    }

    public int Age
    {
        get
        {
            // Just for this example. This will not work for all locals etc but beyond the point here.
            var today = DateTime.Today;
            return today.Year - this.DateOfBirth.Year;
        }
    }

    public DateTime DateOfBirth { get; set; }

    public int Register()
    {
        if (this.Age < 18)
        {
            throw new InvalidOperationException("You must be at least 18 years old");
        }

        int id = this.registrar.Register(this);

        return id;
    }
}

public interface IRegistrar 
{
    public int Register(Customer customer);
}

许多没有域模型的人会在MVC控制器中执行此操作:

A lot of people when they do not have a domain model will do this in an MVC controller:

public ActionResult Search(Customer customer)
{
    var today = DateTime.Today;
    var age = today.Year - this.DateOfBirth.Year;
    if (age < 18)
    {
        // Return an error page or the same page but with error etc.
    }

    // All is good
    int id = this.registrar.Register(customer);

    // The rest of code
}

有一些问题:

  1. 如果开发人员在致电registrar之前忘记进行年龄检查,该怎么办?很多人会说,那真是一个糟糕的开发商.好吧,无论哪种情况,这种类型的代码都容易出现错误.

  1. What if the developer forgets to make the check for age before calling registrar? Many people will say, well that is a bad developer. Well whatever the case is, this type of code is prone to bugs.

产品运行良好,因此CFO决定开放API,因为那里有许多开发人员正在为用户注册制作出色的UI界面,并且他们希望使用我们的API.因此,开发人员继续创建这样的WCF服务:

The product is doing well so CFO decides to open up the API because there are many developers out there who are making great UI interfaces for customer registration and they want to use our API. So the developers go ahead and create a WCF service like this:

public int Register(Customer customer)
{
    var today = DateTime.Today;
    var age = today.Year - this.DateOfBirth.Year;
    if (age < 18)
    {
        // Return a SOAP fault or some other error
    }

    int id = this.registrar.Register(customer);

    // The rest of code
}  

  • 现在,开发人员可以忘记在2个不同的地方进行年龄检查.

  • Now the developers can forget to make the check for age in 2 different places.

    在上述情况下,我们只有一个规则:年龄必须大于18.如果我们有更多的规则和更多的类怎么办?您可以看到它的去向.

    In the above case we only have one rule: Age must be greater than 18. What if we had many more rules and many more classes? You can see where this will go.

    EF模型

    您的EF模型可能是这样的:

    Your EF model may be like this:

    public class Customer
    {
        public int Id { get; set; }
        public DateTime DateOfBirth { get; set; }  
    
        // It may have a foreign key etc.    
    }
    


    应用层模型

    您的MVC视图模型可能是这样的:

    And your model for MVC view maybe like this:

    public class Customer
    {
        // Or instead of Domain.Customer, it may be a CustomerDto which is used
        // to transfer data from one layer or tier to another.
        // But you get the point.
        public Customer(Domain.Customer customer)
        {
            this.DateOfBirth = customer.DateOfBirth;
            this.Age = customer.Age;
            if (this.DateOfBirth.DayOfYear == DateTime.Today.DayOfYear)
            {
                this.Greeting = "Happy Birthday!!!";
            }
        }
        public int Age { get; set; }
    
        [Required(ErrorMessage = "Date of birth is required.")]
        [Display(Name = "Data of birth")]
        public DateTime DateOfBirth { get; set; }
    
        public string Greeting { get; set; }
    }
    

    这是一个问题:使用Display属性可以看到多少个EF模型?我将让您决定EF模型是否应该与UI如何显示有关.只是我的EF模型将在UI中显示的假设是错误的.也许我班上唯一的消费者是另一个Web服务.我不认为Display应该在EF模型中,但是有些人可能与我不同意.你打了电话.

    Here is a question: How many EF models have you seen with the Display attribute? I will let you decide if the EF model should concern itself with how it is displayed in the UI. Just the assumption that my EF model will be displayed in UI is wrong. Maybe the only consumers of my class is another web service. I don't think Display should be in the EF model but some may not agree with me; you make the call.

    关于stackoverflow的问题很多,人们问有时需要PropertyX,有时不是,我该怎么做?好吧,如果您没有在EF模型上放置Required属性并在视图中使用EF模型,那么您将不会遇到此问题.该视图将有一个模型,其中PropertyX是必填字段.该模型将使用Required属性来装饰PropertyX,而不需要PropertyX的视图的另一模型将不会使用Required属性来装饰属性.

    There are loads of questions on stackoverflow about people asking that sometime PropertyX is required and sometimes it is not, how can I do this? Well if you did not put Required attribute on your EF model and use your EF model in your view, then you would not have this issue. There will be one model for the view where PropertyX is a required field. That model will decorate PropertyX with the Required attribute, while another model for the view that does not require PropertyX will not decorate the property with the Required attribute.

    ViewModels

    然后您可以为WPF应用程序的客户提供一个视图模型,并且为前端提供一个javascript视图模型(KnockoutJS视图模型).

    And then you may have a viewmodel for a customer for a WPF application and you may have a javascript viewmodel for the frontend (KnockoutJS viewmodel).

    结论并回答您的问题

    因此,总而言之,您可以拥有与实体模型不同的域模型.您的域模型应该不知道数据库.如果您决定由于规范化而从一个表中删除一列并将其放入自己的表中,则您的实体模型将受到影响.您的域模型不应该受到影响.

    So in conclusion, you can have different domain models than your entity models. Your domain model should be unaware of the database. If you decide to remove a column from one table due to normalization and put it into a table of its own, your entity model will be affected. Your domain model should not be affected.

    我在网络上读过一些论点,例如这种设计花费的时间太长,我只想快速推出一些东西并将其提供给客户并获得报酬".好吧,如果您不打算设计需要维护的产品并添加功能,但是您只是为客户设计一个快速的小型站点,则不要使用此方法.没有设计适用于每种情况.要点是,您的设计应考虑到未来而明智地选择.

    I have read arguments on the net such as "this design takes too long, I just want to roll something out quickly and give it to the client and get paid". Well if you are not designing a product which will need to be maintained and features will be added to it but you are just designing a quick little site for your client then do not use this approach. No design applies to every situation. The point to take away is that your design should be chosen wisely with future in mind.

    从实体模型到域再到MVC的模型的转换也无需手动完成.有一些可以轻松为您完成此操作的库,例如 AutoMapper .

    Also the conversion from entity model to domain to a model for MVC does not need to be done manually. There are libraries out there which will do this for you easily such as AutoMapper.

    但是我不得不承认,网络上有无数的示例,并且在许多应用程序中都有使用,其中在整个应用程序中使用实体模型,并且在所有带有if语句的情况下实现规则.

    But I have to admit, there are tons of examples on the net and also in use in many applications where the entity models are used throughout the application and rules are implemented everywhere with loads of if statements.

    这篇关于DDD和实体框架类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆