C# 域驱动设计中的存储库

C# 域驱动设计中的存储库,c#,domain-driven-design,ddd-repositories,C#,Domain Driven Design,Ddd Repositories,我已经在DDD上挣扎了几个月了,虽然我认为我对一些概念有一个相当好的想法,但对于实现应该如何工作,尤其是如何从数据库加载数据,我不太有信心。我只在C#(零星地)工作了六个月,这对我没有帮助 [原始问题-见下文更新] 在我开始工作的应用程序中,我有一个包含基类的域名称空间,一个使用这些基类执行操作的服务名称空间,然后是一个连接到数据库的存储库和DAL名称空间 我认为最简单的方法是在服务名称空间中使用继承来添加LoadFromDb之类的过程,但是当我开始实现时,我发现这个方法通常需要最多的代码,因为

我已经在DDD上挣扎了几个月了,虽然我认为我对一些概念有一个相当好的想法,但对于实现应该如何工作,尤其是如何从数据库加载数据,我不太有信心。我只在C#(零星地)工作了六个月,这对我没有帮助

[原始问题-见下文更新]

在我开始工作的应用程序中,我有一个包含基类的域名称空间,一个使用这些基类执行操作的服务名称空间,然后是一个连接到数据库的存储库和DAL名称空间

我认为最简单的方法是在服务名称空间中使用继承来添加LoadFromDb之类的过程,但是当我开始实现时,我发现这个方法通常需要最多的代码,因为我必须两次分配所有类属性(一次在存储库名称空间中,然后在服务名称空间中)

这里有一个例子。我可以让选项2和选项3发挥作用,但我希望在精神上与选项1更接近

[更新] 这是第二次尝试。我将域名称空间重命名为Model,将服务名称空间重命名为Domain,我认为这更符合DDD约定。正如建议的那样,我在DAL中使用的存储库名称空间中添加了一个接口。我现在唯一不能做的就是选项1的Load语句,但我想我只需要进一步研究继承

我越来越近了吗

using System;
using System.Data;
using System.Data.OleDb;

namespace Model
{
    public class Request
    {
        public int RequestID{get; set;}
        public string RequestingUser {get; set;}
        public string Title {get; set;}
        public string Description{get; set;}
        public string status {get; set;}
    }
}


namespace App
{
    class MyApp
    {
        void Main()
        {
            //option 1
            Model.Request x = new Domain.dmnRequest(5);

            //option 2
            Model.Request y = new Domain.dmnRequest2(5);

            //option 3
            Model.Request z = new Model.Request();
            Domain.dmnRequest3.loadRequest(5, z);
        }
    }
}

namespace Domain
{
    public class dmnRequest : Model.Request, dal.Request
    {
        public dmnRequest(int requestID)
        {
            //this is what I want to do.  I'm not sure why it's failing
            Load(requestID); 
        }
    }

    public class dmnRequest2 : Model.Request
    {
        public dmnRequest2(int requestID) 
        {
            //option 2; it works but is cumbersome after you hit the 20th property
            dal.Request tmpRequest = new dal.Request();
            tmpRequest.Load(requestID);
            this.RequestID = tmpRequest.RequestID;
            this.RequestingUser = tmpRequest.RequestingUser;
            this.Title = tmpRequest.Title;
            this.Description = tmpRequest.Description;
            this.status = tmpRequest.status;
        }
    }

    public class dmnRequest3
    {
        //option 3.  Much less code, but now I'm not really using inheritance, so in my application layer I can't just declare my variable and use the dmnRequest constructor
        public static void loadRequest(int RequestID, Model.Request MyRequest)
        {
            dal.Request dalRequest = (dal.Request)MyRequest;
            dalRequest.Load(RequestID);
            MyRequest = (Model.Request)dalRequest;
        }
    }
}

namespace repos
{
    public interface SaveMe {void Save(int ID); }
    public interface LoadMe {void Load(int ID); }
}

namespace dal
{
    public class Request : Model.Request, repos.LoadMe
    {
        public void Load(int requestID)
        {
            OleDbConnection dbCon = new OleDbConnection("yaddayadda");
            string Select = "Select * from RequestTable where ID = " + requestID.ToString();
            OleDbDataAdapter dbRequest = new OleDbDataAdapter(Select, dbCon);
            DataSet dsRequest = new DataSet();
            dbRequest.Fill(dsRequest);
            DataRow drRequest = dsRequest.Tables[0].Rows[0];
            this.RequestID = requestID;
            this.RequestingUser = (string)drRequest["User"];
            this.Title = (string)drRequest["Title"];
            this.Description = (string)drRequest["Description"];
            this.status = (string)drRequest["Status"];
        }
    }
}

你完全搞错了。在DDD中,事情非常简单。域只知道由持久层(DAL)中的实际存储库类实现的存储库接口。存储库与数据库一起保存/加载域对象(在DDD中,这些域对象应该是聚合根)

这里没有任何东西应该是静态的,存储库应该从数据库获取它需要的所有数据,然后使用这些数据来恢复对象。存储库始终返回域实体,而不是数据行、数据表、实体框架实体等。这是因为存储库的目的是将域与持久性细节分离

简单地说,域只是说:“嘿,给我这个id的BsuinessEntity”。域告诉存储库要获取什么,而不是如何获取。域并不真正知道涉及到数据库。它所看到的只是一个抽象(存储库接口),用于处理域知道的对象


所有这些都是为了尊重关注点的分离。域关心业务概念和用例,而存储库关心从数据库存储/检索对象

谢谢你的回复。你让我想了很多。
using System;
using System.Data;
using System.Data.OleDb;

namespace Model
{
    public class Request
    {
        public int RequestID{get; set;}
        public string RequestingUser {get; set;}
        public string Title {get; set;}
        public string Description{get; set;}
        public string status {get; set;}
    }
}


namespace App
{
    class MyApp
    {
        void Main()
        {
            //option 1
            Model.Request x = new Domain.dmnRequest(5);

            //option 2
            Model.Request y = new Domain.dmnRequest2(5);

            //option 3
            Model.Request z = new Model.Request();
            Domain.dmnRequest3.loadRequest(5, z);
        }
    }
}

namespace Domain
{
    public class dmnRequest : Model.Request, dal.Request
    {
        public dmnRequest(int requestID)
        {
            //this is what I want to do.  I'm not sure why it's failing
            Load(requestID); 
        }
    }

    public class dmnRequest2 : Model.Request
    {
        public dmnRequest2(int requestID) 
        {
            //option 2; it works but is cumbersome after you hit the 20th property
            dal.Request tmpRequest = new dal.Request();
            tmpRequest.Load(requestID);
            this.RequestID = tmpRequest.RequestID;
            this.RequestingUser = tmpRequest.RequestingUser;
            this.Title = tmpRequest.Title;
            this.Description = tmpRequest.Description;
            this.status = tmpRequest.status;
        }
    }

    public class dmnRequest3
    {
        //option 3.  Much less code, but now I'm not really using inheritance, so in my application layer I can't just declare my variable and use the dmnRequest constructor
        public static void loadRequest(int RequestID, Model.Request MyRequest)
        {
            dal.Request dalRequest = (dal.Request)MyRequest;
            dalRequest.Load(RequestID);
            MyRequest = (Model.Request)dalRequest;
        }
    }
}

namespace repos
{
    public interface SaveMe {void Save(int ID); }
    public interface LoadMe {void Load(int ID); }
}

namespace dal
{
    public class Request : Model.Request, repos.LoadMe
    {
        public void Load(int requestID)
        {
            OleDbConnection dbCon = new OleDbConnection("yaddayadda");
            string Select = "Select * from RequestTable where ID = " + requestID.ToString();
            OleDbDataAdapter dbRequest = new OleDbDataAdapter(Select, dbCon);
            DataSet dsRequest = new DataSet();
            dbRequest.Fill(dsRequest);
            DataRow drRequest = dsRequest.Tables[0].Rows[0];
            this.RequestID = requestID;
            this.RequestingUser = (string)drRequest["User"];
            this.Title = (string)drRequest["Title"];
            this.Description = (string)drRequest["Description"];
            this.status = (string)drRequest["Status"];
        }
    }
}