存储库模式与 DAL

发布于 2024-07-09 03:21:04 字数 306 浏览 4 评论 0 原文

它们是一样的吗? 刚刚看完 Rob Connery 的店面教程,它们似乎是类似的技术。 我的意思是,当我实现 DAL 对象时,我有 GetStuff、Add/Delete 等方法,并且我总是先编写接口,以便稍后可以切换数据库。

我是否混淆了事情?

Are they the same thing? Just finished to watch Rob Connery's Storefront tutorial and they seem to be similar techinques. I mean, when I implement a DAL object I have the GetStuff, Add/Delete etc methods and I always write the interface first so that I can switch db later.

Am I confusing things?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

圈圈圆圆圈圈 2024-07-16 03:21:04

你绝对不是那个混淆视听的人。 :-)

我认为这个问题的答案取决于你想成为一个多么纯粹的人。

如果您想要严格的 DDD 观点,那将带您走一条路。 如果您将存储库视为一种模式,它帮助我们标准化了分隔服务和数据库的层的接口,那么它会让您失望。

从我的角度来看,存储库只是一个明确指定的数据访问层。或者换句话说,是实现数据访问层的标准化方法。 不同的存储库实现之间存在一些差异,但概念是相同的。

有些人会对存储库施加更多的 DDD 约束,而另一些人则将存储库用作数据库和服务层之间的便捷中介。 像 DAL 这样的存储库将服务层与数据访问细节隔离开来。

一个似乎使它们不同的实现问题是,存储库通常是使用采用规范的方法创建的。 存储库将返回满足该规范的数据。 我见过的大多数传统 DAL 都会有一组更大的方法,其中该方法将采用任意数量的参数。 虽然这听起来似乎是一个很小的差异,但当您进入 Linq 和 Expressions 领域时,这是一个大问题。
我们的默认存储库界面如下所示:

public interface IRepository : IDisposable
{
    T[] GetAll<T>();
    T[] GetAll<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
    void Delete<T>(T entity);
    void Add<T>(T entity);
    int SaveChanges();
    DbTransaction BeginTransaction();
}

这是 DAL 还是存储库? 在这种情况下,我猜两者都是。

You're definitely not the one who confuses things. :-)

I think the answer to the question depends on how much of a purist you want to be.

If you want a strict DDD point of view, that will take you down one path. If you look at the repository as a pattern that has helped us standardize the interface of the layer that separates between the services and the database it will take you down another.

The repository from my perspective is just a clearly specified layer of access to data.Or in other words a standardized way to implement your Data Access Layer. There are some differences between different repository implementations, but the concept is the same.

Some people will put more DDD constraints on the repository while others will use the repository as a convenient mediator between the database and the service layer. A repository like a DAL isolates the service layer from data access specifics.

One implementation issue that seems to make them different, is that a repository is often created with methods that take a specification. The repository will return data that satisfies that specification. Most traditional DALs that I have seen, will have a larger set of methods where the method will take any number of parameters. While this may sound like a small difference, it is a big issue when you enter the realms of Linq and Expressions.
Our default repository interface looks like this:

public interface IRepository : IDisposable
{
    T[] GetAll<T>();
    T[] GetAll<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
    void Delete<T>(T entity);
    void Add<T>(T entity);
    int SaveChanges();
    DbTransaction BeginTransaction();
}

Is this a DAL or a repository? In this case I guess its both.

Kim

四叶草在未来唯美盛开 2024-07-16 03:21:04

存储库是一种可以以多种不同方式应用的模式,而数据访问层的职责非常明确:DAL 必须知道如何连接到数据存储以执行 CRUD 操作。

存储库可以是一个DAL,但它也可以位于DAL之前并充当业务对象层和数据层之间的桥梁。 使用哪种实现方式因项目而异。

A repository is a pattern that can be applied in many different ways, while the data access layer has a very clear responsibility: the DAL must know how to connect to your data storage to perform CRUD operations.

A repository can be a DAL, but it can also sit in front of the DAL and act as a bridge between the business object layer and the data layer. Which implementation is used is going to vary from project to project.

杯别 2024-07-16 03:21:04

一个很大的区别是 DAO 是处理域中任何实体持久性的通用方法。 另一方面,存储库仅处理聚合根。

One large difference is that a DAO is a generic way to deal with persistence for any entity in your domain. A repository on the other hand only deals with aggregate roots.

秋风の叶未落 2024-07-16 03:21:04

我正在寻找类似问题的答案,并同意排名最高的两个答案。 试图为自己澄清这一点,我发现如果与存储库模式齐头并进的规范被实现为域模型的一流成员,那么我可以

  • 重用具有不同参数的规范定义,
  • 操作现有规范实例的参数(例如专门化),
  • 组合它们,
  • 执行业务逻辑无需进行任何数据库访问,
  • 当然,可以独立于实际的存储库实现对它们进行单元测试

我什至可以说,除非将存储库模式与规范模式一起使用,否则它并不是真正的“存储库”,而是一个 DAL。 伪代码中的一个人为示例:

specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)

assert that specification200.isSpecialCaseOf(specification100)

specificationAge = new AccountIsOlderThan('2000-01-01')

combinedSpec = new CompositeSpecification(
    SpecificationOperator.And, specification200, specificationAge)

for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
    assert that account.Created < '2000-01-01'
    assert that account.Orders.Count > 200

有关详细信息,请参阅 Fowler 的规范论文(这就是我基于上方)。

DAL 会有专门的方法,例如

IoCManager.InstanceFor<IAccountDAO>()
    .GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')

您可以看到这很快就会变得很麻烦,特别是因为您必须使用这种方法定义每个 DAL/DAO 接口并实现 DAL 查询方法。

在 .NET 中,LINQ 查询可以是实现规范的一种方式,但组合规范(表达式)可能不如使用本地解决方案那么顺利。 这个 SO Question 中描述了一些想法。

I was looking for an answer to a similar question and agree with the two highest-ranked answers. Trying to clarify this for myself, I found that if Specifications, which go hand-in-hand with the Repository pattern, are implemented as first-class members of the domain model, then I can

  • reuse Specification definitions with different parameters,
  • manipulate existing Specification instances' parameters (e.g. to specialize),
  • combine them,
  • perform business logic on them without ever having to do any database access,
  • and, of course, unit-test them independent of actual Repository implementations.

I may even go so far and state that unless the Repository pattern is used together with the Specification pattern, it's not really "Repository," but a DAL. A contrived example in pseudo-code:

specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)

assert that specification200.isSpecialCaseOf(specification100)

specificationAge = new AccountIsOlderThan('2000-01-01')

combinedSpec = new CompositeSpecification(
    SpecificationOperator.And, specification200, specificationAge)

for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
    assert that account.Created < '2000-01-01'
    assert that account.Orders.Count > 200

See Fowler's Specification Essay for details (that's what I based the above on).

A DAL would have specialized methods like

IoCManager.InstanceFor<IAccountDAO>()
    .GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')

You can see how this can quickly become cumbersome, especially since you have to define each of the DAL/DAO interfaces with this approach and implement the DAL query method.

In .NET, LINQ queries can be one way to implement specifications, but combining Specification (expressions) may not be as smooth as with a home-grown solution. Some ideas for that are described in this SO Question.

生生漫 2024-07-16 03:21:04

我个人的观点是,这都是关于映射的,请参阅:http://www.martinfowler.com /eaaCatalog/repository.html。 因此,存储库的输出/输入是域对象,在 DAL 上可以是任何东西。 对我来说,这是一个重要的添加/限制,因为您可以为数据库/服务/任何具有不同布局的内容添加存储库实现,并且您有一个明确的地方可以集中精力进行映射。 如果您不使用该限制并在其他地方进行映射,那么使用不同的方式来表示数据可能会影响不应更改的地方的代码。

My personal opinion is that it is all about mapping, see: http://www.martinfowler.com/eaaCatalog/repository.html. So the output/input from the repository are domain objects, which on the DAL could be anything. For me that is an important addition/restriction, as you can add a repository implementation for a database/service/whatever with a different layout, and you have a clear place to concentrate on doing the mapping. If you were not to use that restriction and have the mapping elsewhere, then having different ways to represent data can impact the code in places it shouldn't be changing.

夜空下最亮的亮点 2024-07-16 03:21:04

这完全取决于解释和上下文。 它们可以非常相似,也可以非常不同,但只要解决方案能完成工作,名字就意味着什么!

It's all about interpretation and context. They can be very similar or indeed very different, but as long as the solution does the job, what is in a name!

假扮的天使 2024-07-16 03:21:04

在外部世界(即客户端代码)中,存储库与 DAL 相同,除了:

(1) 它的插入/更新/删除方法仅限于以数据容器对象作为参数。

(2) 对于读操作,可以采用简单的规范,如 DAL(例如 GetByPK)或高级规范。

在内部,它与数据映射器层(例如实体框架上下文等)一起执行实际的 CRUD 操作。

存储库模式并不意味着什么:-

另外,我发现人们经常感到困惑,除了插入/更新/删除方法之外,还有一个单独的 Save 方法作为存储库模式示例实现,该方法提交由插入执行的所有内存中更改/更新/删除数据库的方法。 我们绝对可以在存储库中拥有 Save 方法,但这不是存储库隔离内存中 CUD(创建、更新、删除)和持久性方法(在数据库中执行实际写入/更改操作)的责任,而是工作单元模式的责任。

希望这可以帮助!

In the external world (i.e. client code) repository is same as DAL, except:

(1) it's insert/update/delete methods is restricted to have the data container object as the parameter.

(2) for read operation it may take simple specification like a DAL (for instance GetByPK) or advanced specification.

Internally it works with a Data Mapper Layer (for instance entity framework context etc) to perform the actual CRUD operation.

What Repository pattern doesn't mean:-

Also, I've seen people often get confused to have a separate Save method as the repository pattern sample implementation besides the Insert/Update/Delete methods which commits all the in-memory changes performed by insert/update/delete methods to database. We can have a Save method definitely in a repository, but that is not the responsibility of repository to isolate in-memory CUD (Create, Update, Delete) and persistence methods (that performs the actual write/change operation in database), but the responsibility of Unit Of Work pattern.

Hope this helps!

勿忘心安 2024-07-16 03:21:04

存储库是一种模式,这是一种以标准化方式实现事物以尽可能重用代码的方法。

Repository is a pattern, this is a way to implement the things in standardized way to reuse the code as we can.

一刻暧昧 2024-07-16 03:21:04

使用存储库模式的优点是模拟您的数据访问层,以便您可以在不调用 DAL 代码的情况下测试业务层代码。 还有其他很大的优势,但这对我来说似乎非常重要。

Advantage of using repository pattern is to mock your data access layer, so that you can test your business layer code without calling DAL code. There are other big advantages but this seems to be very vital to me.

只怪假的太真实 2024-07-16 03:21:04

据我了解,它们的含义基本上是相同的 - 但命名会根据上下文而有所不同。

例如,您可能有一个实现 IRepository 接口的 Dal/Dao 类。

Dal/Dao是数据层术语; 应用程序的较高层会根据存储库进行思考。

From what I understand they can mean basically the same thing - but the naming varies based on context.

For example, you might have a Dal/Dao class that implements an IRepository interface.

Dal/Dao is a data layer term; the higher tiers of your application think in terms of Repositories.

吃→可爱长大的 2024-07-16 03:21:04

那么在大多数(简单)情况下,DAO 是存储库的实现?

据我了解,DAO 似乎精确地处理数据库访问(CRUD - 但没有选择?!),而 Repository 允许您抽象整个数据访问,也许是多个 DAO(可能是不同的数据源)的外观。

我走在正确的道路上吗?

So in most of the (simple) cases DAO is an implementation of Repository?

As far as I understand,it seems that DAO deals precisely with db access (CRUD - No selects though?!) while Repository allows you to abstract the whole data access,perhaps being a facade for multiple DAO (maybe different data sources).

Am I on the right path?

剪不断理还乱 2024-07-16 03:21:04

有人可能会说“存储库”是一个特定的类,而“DAL”是由存储库、DTO、实用程序类和任何其他所需的内容组成的整个层。

One could argue that a "repository" is a specific class and a "DAL" is the entire layer consisting of the repositories, DTOs, utility classes, and anything else that is required.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文