C# DDD-表示层和域层之间的通信

C# DDD-表示层和域层之间的通信,c#,asp.net-mvc,entity-framework,domain-driven-design,C#,Asp.net Mvc,Entity Framework,Domain Driven Design,我在连接我读过的许多帖子中的点时遇到了困难(并且逐渐意识到我可能需要购买Eric Evans的书,而不是依赖大量的互联网材料),我试图坚持领域驱动的设计,但是,在将数据保存回数据库之前,我很难找到从表示层到我的域进行通信的最佳方法。为了简单起见,现在我有一个用户类,它可以有一个作业列表。当用户打开应用程序时,会查询他们的active directory信息,并且只要他们打开应用程序,就会用他们的数据填充此类。然后,用户可以编辑现有作业(如果他们拥有该作业)或创建新作业。我开始创建一个服务类,该类

我在连接我读过的许多帖子中的点时遇到了困难(并且逐渐意识到我可能需要购买Eric Evans的书,而不是依赖大量的互联网材料),我试图坚持领域驱动的设计,但是,在将数据保存回数据库之前,我很难找到从表示层到我的域进行通信的最佳方法。为了简单起见,现在我有一个用户类,它可以有一个作业列表。当用户打开应用程序时,会查询他们的active directory信息,并且只要他们打开应用程序,就会用他们的数据填充此类。然后,用户可以编辑现有作业(如果他们拥有该作业)或创建新作业。我开始创建一个服务类,该类使用我的UnitOfWork类,认为这将作为我的通信,但这正是我的困境所在

当前设置:

DAL-EF 6生成的POCO和DbContext、存储库、工作单元

域-我在本文中提到的实体、存储库和工作单元接口、域接口服务

演示-MVC(内部网),具体服务

问题:

  • 对于这种类型的通信(以及创建我的域类的新实例(例如,创建新作业的方法)来说,服务类是实现的最佳类吗?我意识到我可以使用工厂模式,但我不想变得太复杂?该服务是驻留在域层中,还是为应用层创建单独的项目?那么,接口是否会进入域层,具体实现是否会进入应用层?我觉得这可能会使应用程序过于复杂。另外,服务是WCF还是我可以创建自己的类

  • 如何使用此服务(如果这是最好的方法)将MVC层中的ViewModel映射回域,而不让表示层泄漏到服务中?我读过DTO,但这是服务层的过度使用吗?或者可以将我的域实体公开为ViewModel吗?我一定是想错了。我无法想象在没有泄漏的情况下,控制器中的这种交互会是什么样子。很抱歉问了这么多问题,谢谢

    public class User
    {
        public int Id{ get; set; }
        public string WindowsId{ get; private set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FullName { get { return FirstName + " " + LastName; } }
        public string Email { get; set; }
        public string WorkPhone { get; set; }
    
        public List<Job> Jobs { get; private set; }
    
        public void AddJob(Job job)
        {
            if(job == null)
            throw new Exception("Job is null");
    
            var newJob = new Job(this) //tell the job that this user is creating the job
            {
                Description = job.Description,
                DueDate = job.DueDate,
                Name = job.Name,
                Reason = job.Reason
            };
    
        Jobs.Add(newJob);
        }
    
    }
    
    公共类用户
    {
    公共int Id{get;set;}
    公共字符串WindowsId{get;private set;}
    公共字符串名{get;set;}
    公共字符串LastName{get;set;}
    公共字符串FullName{get{return FirstName+“”+LastName;}}
    公共字符串电子邮件{get;set;}
    公共字符串工作电话{get;set;}
    公共列表作业{get;private set;}
    公共无效添加作业(作业作业)
    {
    如果(作业==null)
    抛出新异常(“作业为空”);
    var newJob=newJob(this)//告诉作业该用户正在创建作业
    {
    描述=工作。描述,
    DueDate=job.DueDate,
    Name=job.Name,
    原因,原因
    };
    Jobs.Add(newJob);
    }
    }
    
  • 更新:我的解决方案

    最后我从每个人的答案中取了一点

    @GranadCoder-我使用EF POCOs作为类作为DTO传递,因为大部分时间是我在ViewModel中向用户显示的数据。因此,它允许我使用DTO作为视图模型

    @克里斯普拉特-你是对的。这样做可以避免很多额外的工作。我所做的只是创建一个包含我所需的所有查询的服务。如果我不得不改变EF,它仍然不会打扰我的其他层。我所要做的就是创建存储库和UOW

    @MilivojMilani—我确实在控制器中有重复的逻辑,因此服务层使我与DRY主体保持一致


    @Yorro-我使用您的观点和参考来加强设计,因为我仍然不确定服务层设置。由于这是一个较小的项目,我用我创建的服务和接口设置了另一个文件夹,如果您使用的是实体框架,则没有WCF远离存储库/工作单元模式。EF本身就是这个模式的一个实现。若您想要抽象实体框架,那个么就实现一个服务模式,该模式将按照您需要的方式返回完全烘焙的数据。最好用一个例子来说明:

    使用EF/Repository

    IQueryable<Post> posts = db.Posts.Where(m => m.BlogId == blog.Id && m.Status == PostStatuses.Published && m.PublishDate <= DateTime.Now).OrderBy(m => m.PublishDate);
    
    或者通过对象列表,您可以使用LINQ:

    var model = posts.Select(m => new PostViewModel
    {
        Title = m.Title,
        Content = m.Content,
        ...
    }
    

    如果你的问题很简单:我怎么做更容易?然后,您可以查看像AutoMapper这样的第三方映射库。

    如果您使用的是实体框架,请远离存储库/工作单元模式。EF本身就是这个模式的一个实现。若您想要抽象实体框架,那个么就实现一个服务模式,该模式将按照您需要的方式返回完全烘焙的数据。最好用一个例子来说明:

    使用EF/Repository

    IQueryable<Post> posts = db.Posts.Where(m => m.BlogId == blog.Id && m.Status == PostStatuses.Published && m.PublishDate <= DateTime.Now).OrderBy(m => m.PublishDate);
    
    或者通过对象列表,您可以使用LINQ:

    var model = posts.Select(m => new PostViewModel
    {
        Title = m.Title,
        Content = m.Content,
        ...
    }
    

    如果你的问题很简单:我怎么做更容易?然后,您可以查看像AutoMapper这样的第三方映射库。

    1。如果您使用的是MVC,您可能有服务层,也可能没有服务层。问自己以下问题-您是否在多个地方使用此功能?如果回答是“是”-使用应用程序服务(而不是域服务)。如果没有,则将其放入MVC控制器本身

    不要在域层中放置任何水合逻辑。DDD中的域层不应该知道关于持久性的任何内容。控制器/应用程序服务应使用存储库接口获取数据,并使用相同的接口保存数据。在您的情况下,您应该只获取和保存用户类,而作业应该作为聚合根子类位于它下面。使用UnitOfWork和Repository是非常好的。这里有一篇关于它的好文章=>

    2.在某些情况下,将域对象用作ViewModel类是完全正常的。在其他更复杂的情况下,必须手动映射属性。映射通常是