C# 服务层与DAL层交互的设计问题

C# 服务层与DAL层交互的设计问题,c#,asp.net-mvc,ef-code-first,onion-architecture,C#,Asp.net Mvc,Ef Code First,Onion Architecture,我的项目有一个设计问题,我不知道如何解决,我有一个保存存储库的DAL层和一个保存“处理器”的服务层。处理器的作用是提供对DAL数据的访问,并执行一些验证和格式化逻辑 我的域对象都至少有一个来自服务层的对象的引用(从存储库中检索它们的属性值)。然而,我面临两个周期性依赖。第一个“循环依赖”来自我的设计,因为我希望DAL返回域对象——我的意思是它是概念性的——第二个来自我的代码 域对象始终至少依赖于一个服务对象 域对象通过调用服务上的方法从存储库中检索其属性 服务的方法调用DAL 然而,问题是,当D

我的项目有一个设计问题,我不知道如何解决,我有一个保存存储库的DAL层和一个保存“处理器”的服务层。处理器的作用是提供对DAL数据的访问,并执行一些验证和格式化逻辑

我的域对象都至少有一个来自服务层的对象的引用(从存储库中检索它们的属性值)。然而,我面临两个周期性依赖。第一个“循环依赖”来自我的设计,因为我希望DAL返回域对象——我的意思是它是概念性的——第二个来自我的代码

  • 域对象始终至少依赖于一个服务对象
  • 域对象通过调用服务上的方法从存储库中检索其属性
  • 服务的方法调用DAL
  • 然而,问题是,当DAL完成他的工作时,他必须返回域对象。但要创建这些对象,他必须注入所需的服务对象依赖项(因为这些依赖项是域对象所必需的)
  • 因此,我的DAL存储库依赖于服务对象
  • 这导致了一个非常明显的周期性依赖。我不知道该如何处理这种情况。最后,我考虑让DAL返回DTO,但它似乎与洋葱架构不兼容。因为DTO是在基础架构中定义的,但是核心层和服务层不应该知道基础架构

    另外,我对更改存储库中所有方法的返回类型并不感兴趣,因为我有数百行代码

    我将感谢任何帮助,谢谢

    更新

    以下是我的代码,让情况更加清楚:

    我的目标(核心):

    这是我的服务接口(在核心)

    这是我的存储库界面(在核心中)

    现在,服务层实现IService,DAL层实现IRepoComplexClass1

    但我的观点是,在我的repo中,我需要构造我的域对象

    这是基础结构层

    using Core;
    
    public Repo : IRepoComplexClass1
    {
       MyComplexClass1 GetMyComplexClassList1()
       {
           //Retrieve all the stuff...
           //... And now it's time to convert the DTOs to Domain Objects
           //I need to write 
    
           //DomainObject.Property1 = new MyComplexClass1(ID, Service);
           //So my Repository has a dependency with my service and my service has a dependency with my repository, (Because my Service Methods, make use of the Repository). Then, Ninject is completely messed up.
       }
    

    我希望现在更清楚。

    首先,在设计系统时,像and(DDD)这样的典型体系结构指南并不适合所有情况。事实上,不鼓励使用这些技术,除非领域具有足够的复杂性来保证成本。因此,您正在建模的领域非常复杂,无法适应更简单的模式

    IMHO,洋葱架构和DDD都试图实现相同的目标。也就是说,能够为复杂逻辑提供一个可编程(并且可能易于移植)的域,而不需要考虑所有其他问题。这就是为什么在洋葱中,应用程序、基础设施、配置和持久性问题处于边缘

    总之,域只是代码。然后,它可以利用这些酷的设计模式来解决手头的复杂问题,而不必担心其他任何事情

    我真的很喜欢洋葱的文章,因为同心屏障的图片不同于分层架构的想法

    在分层体系结构中,很容易通过各层进行垂直、上下思考。例如,您在上面有一个服务,它(通过DTO或ViewModels)与外部世界对话,然后该服务调用业务逻辑,最后,业务逻辑向下调用某个持久层以保持系统的状态

    然而,洋葱架构描述了一种不同的思考方式。您可能仍然在顶部有一个服务,但这是一个应用程序服务。例如,ASP.NET MVC中的控制器了解HTTP、应用程序配置设置和安全会话。但控制器的工作不仅仅是将工作推迟到较低(更智能)的层。任务是尽可能快地从应用程序端映射到域端。简单地说,控制器调用域,要求执行一段复杂的逻辑,得到结果,然后继续执行。控制器是将事物连接在一起的粘合剂(而不是域)

    因此,域是业务域的中心。没有别的了

    这就是为什么有些人抱怨ORM工具需要域实体上的属性。我们希望我们的领域完全没有任何问题,除了手头的问题。所以,普通的旧物体

    因此,域不直接与应用程序服务或存储库对话。事实上,调用的没有任何东西能说明这些事情。域是核心,因此是执行堆栈的末尾

    因此,对于一个非常简单的代码示例(改编自OP):

    存储库:

     // it is only infrastructure if it doesn't know about specific types directly
        public Repository<T>
        {
           public T Find(int id)
           {
               // resolve the entity
               return default(T);   
           }
        }
    
    public class MyComplexClass1
    {
        MyComplexClass1 Property1 {get; }  // requred because cannot be set from outside
        MyComplexClass2 Property2 {get; set;}
        private readonly IService MyService {get; set;}
    
        // no dependency injection frameworks!
        public MyComplexClass1(MyComplexClass1 property1)
        {
           // actually using the constructor to define the required properties
           // MyComplexClass1 is required and MyComplexClass2 is optional
           this.Property1 = property1;
           .....
        }
    
        public ComplexCalculationResult CrazyComplexCalculation(MyComplexClass3 complexity)
        {
           var theAnswer = 42;
           return new ComplexCalculationResult(theAnswer);
        }
    }
    
    public class TheController : Controller
    {
        private readonly IRepository<MyComplexClass1> complexClassRepository;
        private readonly IRepository<ComplexResult> complexResultRepository;
    
        // this can use IoC if needed, no probs
        public TheController(IRepository<MyComplexClass1> complexClassRepository, IRepository<ComplexResult> complexResultRepository)
        {
            this.complexClassRepository = complexClassRepository;
            this.complexResultRepository = complexResultRepository;
        }
    
        // I know about HTTP
        public void Post(int id, int value)
        {
            var entity = this.complexClassRepository.Find(id);
    
            var complex3 = new MyComplexClass3(value);
            var result = entity.CrazyComplexCalculation(complex3);
    
            this.complexResultRepository.Save(result);  
        }
    }
    
    控制器(应用程序服务):

     // it is only infrastructure if it doesn't know about specific types directly
        public Repository<T>
        {
           public T Find(int id)
           {
               // resolve the entity
               return default(T);   
           }
        }
    
    public class MyComplexClass1
    {
        MyComplexClass1 Property1 {get; }  // requred because cannot be set from outside
        MyComplexClass2 Property2 {get; set;}
        private readonly IService MyService {get; set;}
    
        // no dependency injection frameworks!
        public MyComplexClass1(MyComplexClass1 property1)
        {
           // actually using the constructor to define the required properties
           // MyComplexClass1 is required and MyComplexClass2 is optional
           this.Property1 = property1;
           .....
        }
    
        public ComplexCalculationResult CrazyComplexCalculation(MyComplexClass3 complexity)
        {
           var theAnswer = 42;
           return new ComplexCalculationResult(theAnswer);
        }
    }
    
    public class TheController : Controller
    {
        private readonly IRepository<MyComplexClass1> complexClassRepository;
        private readonly IRepository<ComplexResult> complexResultRepository;
    
        // this can use IoC if needed, no probs
        public TheController(IRepository<MyComplexClass1> complexClassRepository, IRepository<ComplexResult> complexResultRepository)
        {
            this.complexClassRepository = complexClassRepository;
            this.complexResultRepository = complexResultRepository;
        }
    
        // I know about HTTP
        public void Post(int id, int value)
        {
            var entity = this.complexClassRepository.Find(id);
    
            var complex3 = new MyComplexClass3(value);
            var result = entity.CrazyComplexCalculation(complex3);
    
            this.complexResultRepository.Save(result);  
        }
    }
    
    public类控制器:控制器
    {
    私有只读IRepository complexClassRepository;
    私有只读IRepository complexResultRepository;
    //如果需要,可以使用IoC,没有问题
    公共控制器(IRepository complexClassRepository、IRepository complexResultRepository)
    {
    this.complexClassRepository=complexClassRepository;
    this.complexResultPostory=complexResultPostory;
    }
    //我知道HTTP
    公共作废帖子(int-id,int-value)
    {
    var entity=this.complexClassRepository.Find(id);
    var complex3=新的MyComplexClass3(值);
    var结果=实体.CrazyComplexCalculation(complex3);
    this.complexResultRepository.Save(结果);
    }
    }
    
    现在,你很快就会想,“哇,那个控制器做得太多了”。例如,如果我们需要50个值来构造
    MyComplexClass3
    ,怎么样。这就是洋葱建筑的辉煌之处。那里