尝试在此处制作一个非常简单的存储库和服务层模式。 (.net 4,c#,linq,尽管这个问题是部分语言 - 敏捷的)。注意:这只是研发。

我的目标是最大程度地减少服务层中的方法定义的量。

这是我的存储库合同:

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

那里没有新的。

现在,这是我(尝试)在我的服务合同中拥有的东西:

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

从本质上讲,任何特定的“ foo”都有许多属性(ID,名称等),我希望能够搜索。

因此,我不想让每个不同属性的1倍查找方法,我只想要一个 - 这样,当我创建额外的属性时,我不必修改合同。

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

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

  • 这是糟糕的设计吗?如果是这样,有什么选择?
  • 如何在服务层中实现此过滤?我是否必须检查设置“ foosearchargs”的属性,然后继续过滤? (如果是这样,请查询。在哪里,如果这个地方查询,等等)任何人都有一个聪明的linq iEnumerable扩展方法来做到这一点吗? (IE repository.WhereMeetsSearchCriteria(fooSearchArgs))

感谢帮助。

有帮助吗?

解决方案

我们使用非常相似的东西。您需要决定的一件事是,您是否要在存储库之外揭示可视性。您的查找方法返回iEnumerable,这可能是从您的子句中返回的可音机。

返回Iqueryable的优点是,您可以在存储库层之外进一步完善您的条件。

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

只有在您使用返回的数据时,该表达式才会被编译,这是不利的。因为您只有在实际使用结果时才能点击数据库,您最终可能会在会话(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();
    }
}

查询运行后,从规范中返回的结果可汇总的存储库toarray或Tolist,以便在此处评估查询。尽管这似乎不如揭露可见性的灵活性,但它具有几个优势。

  1. 查询立即执行,并防止在会话结束后对数据库进行调用。
  2. 由于您的查询现在已捆绑到规格中,因此可以测试单位。
  3. 规格是可重复使用的,这意味着您在尝试运行类似的查询时没有代码重复,并且查询中的任何错误都只需要在一个地方固定。
  4. 使用正确的实施方式,您还可以将您的规格链接在一起。

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

其他提示

正在通过a 功能 作为服务层查找方法的参数,而不是foosearchargs,一个选项?枚举具有将func作为参数的Where方法(LINQ),因此您可以使用它来过滤结果。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top