gpt4 book ai didi

c# - 存储库/服务层设计模式的建议

转载 作者:行者123 更新时间:2023-11-30 22:44:09 28 4
gpt4 key购买 nike

尝试在这里创建一个非常简单的存储库和服务层模式。 (.NET 4、C#、LINQ,尽管这个问题部分与语言无关)。注意:这只是研发。

我的目标是尽量减少服务层中方法定义的数量。

这是我的存储合约:

interface IFooRepository
{
IEnumerable<Foo> Find();
void Insert(Foo foo);
void Update(Foo foo);
void Delete(Foo foo);
}

没有什么新鲜事。

现在,这是我(试图)在我的服务契约(Contract)中包含的内容:

interface IFooDataService
{
public IEnumerable<Foo> Find(FooSearchArgs searchArgs);
}

本质上,任何特定的“Foo”都有许多属性(id、名称等),我希望能够根据这些属性进行搜索。

所以,我不想为每个不同的属性使用 1x Find 方法,我只想要一个 - 这样当我创建额外的属性时,我不必修改契约(Contract)。

“FooSearchArgs”只是一个简单的 POCO,具有所有不同的“Foo”属性。

所以,这就是我想要做的,这是我的问题:

  • 这是糟糕的设计吗?如果可以,有哪些替代方案?
  • 我如何在服务层实现这种过滤?我是否必须检查设置了“FooSearchArgs”的哪些属性,然后继续过滤? (如果是这样,则 query.where,如果是,query.where 等)任何人都知道一个聪明的 LINQ IEnumerable 扩展方法来执行此操作吗? (即 repository.WhereMeetsSearchCriteria(fooSearchArgs))

感谢您的帮助。

最佳答案

我们使用的东西非常相似。您需要决定的一件事是您是否要在存储库外部公开 IQueryable。您的 find 方法返回 IEnumerable,它可能是从您的 when 子句返回的 IQueryable。

返回 IQueryable 的优点是您可以在存储库层之外进一步细化您的标准。

repository.Find(predicate).Where(x => x.SomeValue == 1);

只有当你要使用返回的数据时,表达式才会被编译,缺点就在这里。因为您只有在实际开始使用结果时才访问数据库,所以您最终可能会在 session (nhibernate) 或连接关闭后尝试调用数据库。

我个人的偏好是使用规范模式,您可以在其中传递查找方法,并使用 ISpecification 对象进行查询。

public interface ISpecification<TCandidate>
{
IQueryable<TCandidate> GetSatisfyingElements(IQueryable<TCandidate> source);
}

public class TestSpecification : ISpecification<TestEntity>
{
public IQueryable<TestEntity> GetSatisfyingElements(IQueryable<TestEntity> source)
{
return source.Where(x => x.SomeValue == 2);
}
}

public class ActiveRecordFooRepository: IFooRepository
{
...

public IEnumerable<TEntity> Find<TEntity>(ISpecification<TEntity> specification) where TEntity : class
{
...

return specification.GetSatisfyingElements(ActiveRecordLinq.AsQueryable<TEntity>()).ToArray();

...
}

public TEntity FindFirst<TEntity>(ISpecification<TEntity> specification) where TEntity : class
{
return specification.GetSatisfyingElements(ActiveRecordLinq.AsQueryable<TEntity>()).First();
}
}

查询运行后,存储库对从规范返回的结果 IQueryable 调用 ToArray 或 ToList,以便当场计算查询。虽然这看起来不如公开 IQueryable 灵活,但它有几个优点。

  1. 查询会立即执行,并防止在 session 关闭后调用数据库。
  2. 因为您的查询现在已捆绑到规范中,所以它们可以进行单元测试。
  3. 规范是可重用的,这意味着您在尝试运行类似查询时不会出现代码重复,并且查询中的任何错误只需在一处修复。
  4. 通过正确的实现方式,您还可以将规范链接在一起。

repository.Find(
firstSpecification
.And(secondSpecification)
.Or(thirdSpecification)
.OrderBy(orderBySpecification));

关于c# - 存储库/服务层设计模式的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3562077/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com