在项目中使用服务类和存储库类?

时间:2018-04-03 09:30:36

标签: c# .net

我最近进入了C#的高级阶段,并且我看到很多应用程序实现了丢失耦合和依赖注入。我已经看过"服务"与课程相关的很多,我想你会称它们为服务类?我还看到这个项目中的课程包括Repository这个词,比如说你有一个名为“玩家”的人,还有2个以上的课程和玩家服务'和' PlayerRepository'类。

我检查了Linda,TreeHouse,Udemy和许多其他网站。我甚至谷歌这个主题,但它似乎带来了数百个结果所有导致不同的事情。这些链接中没有一个真正以简单明了的细节回答我的问题,至少我无法理解。

任何人都可以帮忙解释一下吗?为什么我需要它们,何时使用它们,它们是什么?

2 个答案:

答案 0 :(得分:0)

嗯,很难在没有看到代码的情况下做出具体的解释,但总的来说,Repository的概念是指数据层组件和术语服务 - 主要是在ASP.NET世界中指的是业务层组件。

您可以将这些图层彼此分开,以便可以单独维护,测试和扩展它们。理想的体系结构通过接口公开这些层的功能 - 尤其是存储库层。在Service层上,您可以通过构造函数将这些依赖项作为Interfaces。使用IoC容器和依赖注入模式,您可以将具体类注册到这些接口,并在中心位置构建对象。对象组合根。这允许您在中心位置轻松管理依赖项,而不是实例化每个依赖项,在代码中分散的位置传递。

这个答案只是一个给你概述的指针。这些是您应该通过自我研究和消化深入研究的主题。

答案 1 :(得分:0)

Repository模式用于抽象出类的持久化方式。这允许您更改基础数据库或ORM映射器,而不会影响持久化类。请参阅Using Repository Pattern for Abstracting Data Access from a Cache and Data Store

如果多个类参与某个用例,则使用服务,并且这些类中没有一个应该负责协调其他类。 (也许这些类甚至不能直接引用彼此。)在这种情况下,将处理类之间相互作用的代码放入服务方法中,并将受影响的对象传递给它。

请注意,如果受影响的类处于直接的父子关系中,您可以让父级直接协调其子级,而不引入服务。但这可能导致代码难以理解。

让我举个例子:假设我们想提交交易。提交事务后,我们希望使用最近事务的(非规范化)时间戳更新具有事务的Person。如您所见,Person没有直接引用该事务。

public class Person {

    public long Id { get; set; }

    public string Name { get; set; }

    public DateTime? LastTransactionTimestamp { get; set; }
}

public class Transaction {

     public long Id { get; set; }

     public long PersonId { get; set; }

     public DateTime Timestamp { get; set; }

     public void Commit() {
         Timestamp = DateTime.Now;
     }
}

现在我们遇到了应该把逻辑放在哪里的问题。如果我们将它放入Person类,则需要Repository访问权来加载Transaction(因为它没有直接引用)。但它应该只关注存储自己的数据,而不是从数据库加载不相关的数据。如果我们将它放入Transaction类,它不知道它是否是此Person的最新Transaction(因为它没有看到其他事务)。

所以解决方案是将逻辑放入服务中。如果服务需要数据库访问,我们会在其中注入一个存储库。

public class PersonTransactionService {

    private readonly IDbSet<Transaction> _allTransactions;

    public PersonTransactionService(IDbSet<Transaction> allTransactions) {
        _allTransactions = allTransactions;
    }

    public void Commit(Person person, Transaction transaction) {
        transaction.Commit();

        var mostRecent = _allTransactions
            .Where(t => t.PersonId == person.Id)
            .OrderBy(t => t.Timestamp)
            .LastOrDefault();

        if (mostRecent != null) {
            person.LastTransactionTimestamp = mostRecent.Timestamp;
        }
    }
}