Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 存储库的职责应该有多有限?_Oop_Architecture_Domain Driven Design_Data Access Layer - Fatal编程技术网

Oop 存储库的职责应该有多有限?

Oop 存储库的职责应该有多有限?,oop,architecture,domain-driven-design,data-access-layer,Oop,Architecture,Domain Driven Design,Data Access Layer,一些阅读材料告诉我,我的存储库(1)除了通过配置的(注入的)数据提供程序直接执行CRUD操作外,什么都不做,但在小项目中,我发现添加整个服务层也有点过分 例如,我的应用程序处理“银行”分行和客户。现在,如果我的用户为每个工作会话“打开”一个分支,并且每个新客户机都被分配给该分支,我会倾向于将我编写的AppContext单例注入到我的ClientRepository中,以跟踪环境应用程序属性,例如当前打开的分支,并让该对象将正确的BranchID分配给新客户机记录 我知道这在最纯粹的意义上是不正确

一些阅读材料告诉我,我的存储库(1)除了通过配置的(注入的)数据提供程序直接执行CRUD操作外,什么都不做,但在小项目中,我发现添加整个服务层也有点过分

例如,我的应用程序处理“银行”分行和客户。现在,如果我的用户为每个工作会话“打开”一个分支,并且每个新客户机都被分配给该分支,我会倾向于将我编写的AppContext单例注入到我的ClientRepository中,以跟踪环境应用程序属性,例如当前打开的分支,并让该对象将正确的BranchID分配给新客户机记录

我知道这在最纯粹的意义上是不正确的,但我这里说的是基本的2层应用程序,UI和数据。唯一的业务“逻辑”实际上是在查询数据库时完成的。这里有没有更适合我的图案


(1)

我个人同意,存储库应该尽可能像您在第一段中描述的那样“干净”

根据经验,我还通过在CRUD函数中编写业务逻辑代码来“欺骗”,这通常需要将其他存储库作为属性

在ASP.net中工作时,我利用了泛型和事件处理

public class Repository<T, DC>
        where T : class
        where DC : DataContext, new()
{
    public delegate void RecordInsertedHandler(object s, BasicEventArgs<T> e);
    public event RecordInsertedHandler RecordInserted;

    public delegate void RecordDeletedHandler(object s, BasicEventArgs<T> e);
    public event RecordDeletedHandler RecordDeleted;

    public delegate void RecordObtainedHandler(object s, BasicEventArgs<T> e);
    public event RecordObtainedHandler RecordObtained;

    public delegate void RecordUpdatedHandler(object s, BasicEventArgs<T> e);
    public event RecordUpdatedHandler RecordUpdated;

    protected DC dc;

    public Repository(string connectionString="")
    {
        dc = ((connectionString == null) || (connectionString == "")) ? new DC() :   DynamicTypes.Instantiate<DC>(connectionString);  // See code below for DynamicTypes:

    }

    // There are similar functions for other events not shown.
    protected void OnRecordInserted(BasicEventArgs<T> obj)
    {
        if (RecordInserted != null)
        {
            RecordInserted(this, obj);
        }
    }

    // Only the Insert is shown here.
    private void Insert(T obj)
    {
        dc.GetTable<T>().InsertOnSubmit(obj);
        dc.SubmitChanges();

        OnRecordInserted(new BasicEventArgs<T>(obj));
    }
}
公共类存储库
T:在哪里上课
其中DC:DataContext,new()
{
公共委托无效记录插入句柄(对象s,基本目标e);
公共事件记录插入Handler记录插入;
公共委托无效记录删除Handler(对象s、基本目标e);
公共事件记录deletedHandler记录已删除;
公共委托无效记录获取处理程序(对象s、基本目标e);
获取公共事件记录获取处理程序记录;
公共委托void RecordUpdatedHandler(对象s、基本目标e);
公共事件RecordUpdatedHandler RecordUpdated;
保护直流;
公共存储库(字符串connectionString=“”)
{
dc=((connectionString==null)| |(connectionString==“”)?新建dc():DynamicTypes.Instantiate(connectionString);//有关DynamicTypes,请参见下面的代码:
}
//对于未显示的其他事件,也有类似的功能。
已插入受保护的无效记录(基本目标)
{
if(RecordInserted!=null)
{
记录插入(本,obj);
}
}
//此处仅显示插入内容。
专用无效插入(T obj)
{
dc.GetTable().InsertOnSubmit(obj);
dc.提交更改();
OnRecordInserted(新基本目标(obj));
}
}
基本思想是在常规CRUD函数的正确位置触发/调用这些事件。我假定您的存储库将是ASP.net页面或Windows窗体的成员。这些容器将成为“事件侦听器”,因为它们可以操纵UI

动态类型:

public static class DynamicTypes
{        
    public static T Instantiate<T>(params object[] args)
    {
        return (T)Activator.CreateInstance(typeof(T), args);
    }
}
公共静态类动态类型
{        
公共静态T实例化(参数对象[]args)
{
return(T)Activator.CreateInstance(typeof(T),args);
}
}
基本目标:

public class BasicEventArgs<T> : EventArgs
{
    private T _Data;
    private string _Message;

    public BasicEventArgs(T data, string message="") : base()
    {
        _Data = data;
        _Message = message;
    }

    public T Data
    {
        get { return _Data; }
        set { _Data = value; }
    }

    public string Message
    {
        get { return _Message; }
        set { _Message = value; }
    }
}
公共类基本事件args:EventArgs
{
私人T_数据;
私有字符串消息;
public BasicEventArgs(T数据,字符串消息=”):base()
{
_数据=数据;
_消息=消息;
}
公共T数据
{
获取{return_Data;}
设置{u Data=value;}
}
公共字符串消息
{
获取{return\u Message;}
设置{u Message=value;}
}
}
存储库:

public class BranceshRepository : Repository<Branch, YourDataContext>
{
     public BranchesRepository(string connectionString="") : base(connectionString)
     {
     }
}

public class ClientsRepository : Repository<Client, YourDataContext>
{
     public ClientsRepository(string connectionString="") : base(connectionString)
     {
     }
}
公共类BranceShareRepository:存储库
{
public BranchesRepository(string connectionString=”“):base(connectionString)
{
}
}
公共类客户端存储库:存储库
{
public ClientsRepository(string connectionString=”“):基本(connectionString)
{
}
}
例如,现在我们有一个ASP.net页面:

public partial class MyPage : Page
{
      protected ClientsRepository _ClientsRepository;
      protected BranchesRepository _BranchesRepository;

      protected void Page_Load(object s, EventArgs e);
      {
           _ClientsRepository = new ClientsRepository(...);
           _BranchesRepository = new BranchesRepository(...);

           _BranchesRepository.RecordInserted += new Repository<Branch,YourDataContext>.RecordInsertedHandler(OnBranchInserted);
           _ClientsRepository.RecordInserted += new RepositoryM<Client, YourDataContext>.RecordInsertedHandler(OnClientInserted);
      }

      protected void OnBranchInserted(object s, BasicEventArgs<Branch> e)
      {
             /* e.Data is your newly-inserted branch with the newly-generated Id
                from the database. You may save this branch to Session for
                later use when your user inserts a new client.
               */
      }

      protected void OnClientInserted(object s, BasicEventArgs<Client> e)
      {
              Branch currentBranch = (Branch)Session["Branch"];
              e.Data.BranchId = currentBranch.Id;
              _ClientsRepository.Update(e.Data);                
      }

      // Control event handlers not shown, like CreateClient_BT_Click, for example.
}
公共部分类MyPage:Page
{
受保护的客户储蓄(ClientsRepository);;
受保护的BranchesRepository\u BranchesRepository;
受保护的无效页面加载(对象s、事件参数e);
{
_ClientsRepository=新的ClientsRepository(…);
_BranchesRepository=新建BranchesRepository(…);
_BranchesRepository.RecordInserted+=新存储库.RecordInsertedHandler(OnBranchInserted);
_ClientsRepository.RecordInserted+=新的RepositoryM.RecordInsertedHandler(OnClientInserted);
}
BranchInserted上受保护的空(对象s、基本目标e)
{
/*e.数据是您使用新生成的Id新插入的分支
从数据库中。您可以将此分支保存到会话以供
稍后在用户插入新客户端时使用。
*/
}
客户端插入时受保护的无效(对象s、基本目标e)
{
分支当前分支=(分支)会话[“分支”];
e、 Data.BranchId=currentBranch.Id;
_客户存储更新(如数据);
}
//未显示控件事件处理程序,例如CreateClient_BT_Click。
}

通过这种方式,您不需要在客户端Repository中注入单例,并且您可以在这些事件处理程序中完全访问您的UI。

在我们的团队中,我们正在追求(至少3或4年左右)一个完美的理念,即必须将所有业务逻辑从业务逻辑中完全删除。所以我们建立了很多服务

我们相信,在这个完美的世界里,如果你有一个特定的范围,你就会为它创造一个服务。正如Mickael之前提到的,“ClientsRepository”将为客户机提供SCRUD(s-search),只有我们称之为ClientsService(就像在服务中告诉您有关客户机的一切一样)。这里你有一个威胁,当一个不知情的开发人员或一个在极端压力或截止日期下的开发人员看到这样的代码时:

public ModifyClientResponse ModifyClient(ModifyClientRequest request){

    ClientEntity clientEntity=new ClientEntity();
    ModifyClientResponse clientResponse = new ModifyClientResponse();

    ClientMapper mapper=new ClientMapper();
    mapper.Map(request.Client, clientEntity);

    clientEntity.Update();

    ClientDTO responseClientDto=new ClientDTO();
    mapper.Map(clientEntity, responseClient);

    clientResponse.Client=responseClientDto;

    return clientResponse
}
public ModifyClientResponse ModifyClient(ModifyClientRequest request){

    ClientEntity clientEntity=new ClientEntity();
    ModifyClientResponse clientResponse = new ModifyClientResponse();

    ClientMapper mapper=new ClientMapper();
    mapper.Map(request.Client, clientEntity);

    clientEntity.Update();

    if(clientEntity.Address.DataModification==DataModification.Modified){
    // all the silly business logics about address being changed
    }

    ClientDTO responseClientDto=new ClientDTO();
    mapper.Map(clientEntity, responseClient);

    clientResponse.Client=responseClientDto;

    return clientResponse
}
我认为这很简单。同一个开发者得到了