存储库中的复杂业务逻辑

时间:2010-12-17 20:28:35

标签: asp.net-mvc

我在存储库中有一个具有非常复杂的业务逻辑的方法。我刚刚读到存储库中应该没有业务逻辑。

从这种方法中删除业务逻辑将要求我在两个其他存储库之间分配逻辑(因为它涉及另外两个实体)。

然后我的问题是 - 我应该用什么模式来实现这个复杂的逻辑?它需要使用这三个存储库,但我不能将它放在控制器中,因为我需要重用它。谢谢你的帮助。

3 个答案:

答案 0 :(得分:9)

复杂的业务逻辑通常会进入服务层。服务可能依赖于一个或多个存储库来对您的模型执行CRUD操作。因此,表示业务操作的单个服务操作可以取决于多个简单操作。然后,您可以在控制器和其他应用程序中重用此服务层。

显然,您的服务不应该依赖于特定的存储库实现。为了在服务层和存储库之间提供较弱的耦合,您可以使用接口。这是一个例子:

public interface IProductsRepository { }
public interface IOrdersRepository { }
...

public interface ISomeService 
{
    void SomeBusinessOperation();
}

public class SomeServiceImpl: ISomeService
{
    private readonly IProductsRepository _productsRepository;
    private readonly IOrdersRepository _ordersRepository;

    public SomeServiceImpl(
        IProductsRepository productsRepository, 
        IOrdersRepository ordersRepository
    )
    {
        _productsRepository = productsRepository;
        _ordersRepository = ordersRepository;
    }

    public void SomeBusinessOperation()
    {
        // TODO: use the repositories to implement the business operation
    }
}

现在剩下的就是配置你的DI框架,将这个特定的服务注入你的控制器。

public class FooController : Controller
{
    private readonly ISomeService _service;
    public FooController(ISomeService service)
    {
        _service = service;
    }

    public ActionResult Index()
    {
        // TODO: Use the business operation here.
    }
}

您可以看到接口如何允许我们在层之间提供弱耦合。所有管道都由DI框架执行,一切都是透明的,并且易于单元测试。

答案 1 :(得分:2)

我会使用域驱动的设计方法。关于DDD的一本非常好的书如下:.NET Domain-Driven Design with C#: Problem-Design-Solution。另请参阅Fowlers Enterprise Patterns和Evans Domain Driven Design书籍。基本思想是存储库基本上是基础设施。所有域逻辑都进入您的模型。

示例存储库方法如下所示:

public void InsertAddresse(Company company)
{
    foreach (Address address in company.Addresses)
    {
        this.InsertAddress(address, company.Key, (company.HeadquartersAddress == address));
    }
}

另一方面,模型对象如下所示:

public class Contact : Person, IAggregateRoot, IHasAddresses
{
    private string jobTitle;
    private string email;
    private string phoneNumber;
    private string mobilePhoneNumber;
    private string faxNumber;
    private string remarks;
    private Company currentCompany;
    private IList<Address> addresses;

    public Contact()
        : this(null)
    {
    }

    public Contact(object key)
        : this(key, null, null)
    {
    }

    public Contact(object key, string firstName, string lastName) 
        : base(key, firstName, lastName)
    {
        this.jobTitle = string.Empty;
        this.email = string.Empty;
        this.phoneNumber = string.Empty;
        this.mobilePhoneNumber = string.Empty;
        this.faxNumber = string.Empty;
        this.remarks = string.Empty;
        this.currentCompany = null;
        this.addresses = new List<Address>();
    }

    public string JobTitle
    {
        get { return this.jobTitle; }
        set { this.jobTitle = value; }
    }

    public string Email
    {
        get { return this.email; }
        set { this.email = value; }
    }

    public string PhoneNumber
    {
        get { return this.phoneNumber; }
        set { this.phoneNumber = value; }
    }

    public string MobilePhoneNumber
    {
        get { return this.mobilePhoneNumber; }
        set { this.mobilePhoneNumber = value; }
    }

    public string FaxNumber
    {
        get { return this.faxNumber; }
        set { this.faxNumber = value; }
    }

    public string Remarks
    {
        get { return this.remarks; }
        set { this.remarks = value; }
    }

    public Company CurrentCompany
    {
        get { return this.currentCompany; }
        set { this.currentCompany = value; }
    }

    public IList<Address> Addresses
    {
        get { return this.addresses; }
    }

    protected override void Validate()
    {
        //some logic here
    }

    protected override BrokenRuleMessages GetBrokenRuleMessages()
    {
        return new ContactRuleMessages();
    }
}

答案 2 :(得分:1)

我认为你的超级存储库只是打破了单一责任原则。 我会尽可能简单地保存存储库(KISS模式;),并在控制器和存储库之间创建其他层,e.q。业务层。

要重用和简化代码,请查看依赖注入(实现IoC)

实际上我建议看一下SOLID原则。