存储库模式熟悉超棒的存储库模式
存储库模式是另一种抽象,就像计算机科学中的大多数概念一样。它适用于多种不同的语言。事实上,很多开发人员都在使用存储库模式,只是没有意识到而已。
在这篇文章中,我将改造一段代码。首先,我们先来看一下这段代码,它从数据库加载一条记录。获取到记录后,它会返回给调用者。我们来看一些代码。
需要改进
我们从数据库中加载的记录是PersonModel
。
public class PersonModel
{
public string Name { get; set; }
public int Age { get; set; }
}
从数据库加载人员的服务是ICompanyLogic
。它由以下方法定义组成。
public interface ICompanyLogic
{
PersonModel GetPersonByName(string name);
}
的实施ICompanyLogic
由 负责CompanyLogic
。
public class CompanyLogic: ICompanyLogic
{
private IPersonDataContext _personDataContext;
public PersonService(IPersonDataContext personDataContext)
{
_personDataContext= personDataContext;
}
public PersonModel GetPersonByName(string name)
{
using(var ctx = _personDataContext.NewContext())
{
var person = ctx.People.First(p => p.Name.Equals(name));
return person;
}
}
}
到目前为止,情况还不算太糟。我们有一个业务服务CompanyLogic
,可以从数据库中检索单个人员。
但是我们又有一个新的需求,需要一种从其他数据库加载公司信息的方法。所以我们需要添加一个新方法并进行扩展CompanyLogic
。
CompanyModel
表示存储在公司数据库中的模型。
public class CompanyModel
{
public string Name { get; set; }
public int Size { get; set; }
public bool Public { get; set; }
}
我们扩展了CompanyLogic
一种按名称返回公司的方法。
public class CompanyLogic: ICompanyLogic
{
private IPersonDataContext _personDataContext;
private ICompanyDataContext _companyDataContext;
public PersonService(IPersonDataContext personDataContext,
ICompanyDataContext companyDataContext)
{
_personDataContext= personDataContext;
_companyDataContext = companyDataContext;
}
public PersonModel GetPersonByName(string name)
{
using(var ctx = _personDataContext.NewContext())
{
var person = ctx.People.First(p => p.Name.Equals(name));
return person;
}
}
public CompanyModel GetCompanyByName(string companyName)
{
using(var ctx = _companyDataContext.NewContext())
{
var person = ctx.Company.First(c => c.Name.Equals(companyName));
return person;
}
}
}
现在我们开始看到这个初始解决方案存在的问题了。以下是一些不太理想的地方。
CompanyLogic
,知道如何访问两个不同的数据库。- 我们的
using
语句中存在重复的代码。 - 我们的逻辑知道人员和公司是如何存储的。
GetPersonByName
并且GetCompanyByName
如果不引入全部,就无法重复使用CompanyLogic
。
除了所有这些之外,我们该如何CompanyLogic
在当前状态下进行测试?我们必须模拟个人和公司的数据上下文,才能拥有真实的数据库记录。这是可以做到的。但我们的精力应该放在测试逻辑上,而不是模拟数据库对象。
实现存储库模式
存储库模式在数据访问之上添加了一个抽象层。
一点点抽象就能带来很大的帮助。使用存储库模式,我们可以添加一层薄薄的抽象来访问人员和公司数据库。然后CompanyLogic
,任何其他逻辑都可以利用这些抽象。
让我们首先创建我们的IPersonRepository
界面及其附带的实现。
public interface IPersonRepository
{
PersonModel GetPersonByName(string name);
}
public class PersonRepository: IPersonRepository
{
private IPersonDataContext _personDataContext;
public PersonRepository(IPersonDataContext personDataContext)
{
_personDataContext= personDataContext;
}
public PersonModel GetPersonByName(string name)
{
using(var ctx = _personDataContext.NewContext())
{
return ctx.People.First(p => p.Name.Equals(name));
}
}
}
然后我们可以为公司做一些非常类似的事情。我们可以创建ICompanyRepository
界面及其实现。
public interface ICompanyRepository
{
PersonModel GetCompanyByName(string name);
}
public class CompanyRepository: ICompanyRepository
{
private ICompanyDataContext _companyDataContext;
public CompanyRepository(ICompanyDataContextcompanyDataContext)
{
_companyDataContext= personDataContext;
}
public CompanyModel GetCompanyByName(string name)
{
using(var ctx = _companyDataContext.NewContext())
{
return ctx.Company.First(p => p.Name.Equals(name));
}
}
}
我们现在有了两个独立的存储库。PersonRepository
知道如何从人员数据库中按姓名加载指定的人员。CompanyRepository
可以从公司数据库中按名称加载公司。现在让我们重构一下CompanyLogic
,利用这些存储库来代替数据上下文。
public class CompanyLogic: ICompanyLogic
{
private IPersonRepository _personRepo;
private ICompanyRepository _companyRepo;
public PersonService(IPersonRepository personRepo,
ICompanyRepository companyRepo)
{
_personRepo= personRepo;
_companyRepo= companyRepo;
}
public PersonModel GetPersonByName(string name)
{
return _personRepo.GetPersonByName(name);
}
public CompanyModel GetCompanyByName(string companyName)
{
return _companyRepo.GetCompanyByName(companyName);
}
}
瞧,我们的逻辑层不再了解任何数据库知识。我们已经抽象出了如何加载个人和公司数据。那么,我们获得了什么好处呢?
- 存储库接口是可重用的。它们可以在其他逻辑层中使用,而无需进行任何更改。
- 测试变得简单多了。我们模拟了接口响应,这样就可以专注于测试逻辑了。
- 个人和公司的数据库访问代码集中在一个地方进行管理。
- 可以在存储库级别进行优化。接口已定义并达成一致。之后,负责存储库的开发人员可以按照自己认为合适的方式存储数据。
存储库模式为我们提供了良好的数据抽象。它适用于多种语言。其核心在于,数据访问应该是一个单一职责接口。该接口可以注入到业务层,以添加任何额外的逻辑。
渴望了解亚马逊网络服务吗?
许多人渴望学习 Amazon Web Services。受此启发,我创建了一门课程,专注于学习如何使用 Amazon Web Services。课程重点关注静态网站的托管、安全和交付问题。您可以通过构建解决方案来学习 S3、API 网关、CloudFront、Lambda 和 WAF 等服务。
关于 AWS 的信息浩如烟海,很容易迷失方向,学习进度停滞不前。解决这个问题,我们可以梳理信息,加快学习速度。我写这本书和视频课程的目的是与大家分享我学到的知识。
听起来很有趣?点击这里,查看登陆页面了解更多信息,并选择适合您的套餐。
文章来源:https://dev.to/kylegalbraith/getting-familiar-with-the-awesome-repository-pattern--1ao3