繁体   English   中英

要返回IQueryable <T>或不返回IQueryable <T>

[英]To return IQueryable<T> or not return IQueryable<T>

我有一个存储库类,它包装了我的LINQ to SQL数据上下文。 存储库类是一个业务线类,包含所有数据层逻辑(以及缓存等)。

这是我的repo界面的v1。

public interface ILocationRepository
{
    IList<Location> FindAll();
    IList<Location> FindForState(State state);
    IList<Location> FindForPostCode(string postCode);
}

但是为了处理FindAll的分页,我正在讨论是否要公开IQueryable <ILocation>而不是IList来简化诸如分页之类的情况的接口。

从数据仓库中暴露IQueryable的利弊是什么?

很感谢任何形式的帮助。

专业人士; 可组合:

  • 呼叫者可以添加过滤器
  • 呼叫者可以添加分页
  • 呼叫者可以添加排序
  • 等等

缺点; 非可测性:

  • 您的存储库不再适用于单元可测试; 你不能依赖:它工作,b:它做什么 ;
    • 调用者可以添加一个不可翻译的函数(即没有TSQL映射;在运行时中断)
    • 调用者可以添加一个过滤器/排序,使其像狗一样运行
  • 由于调用者希望IQueryable<T>是可组合的,它排除了不可组合的实现 - 或者它迫使你为它们编写自己的查询提供者
  • 这意味着您无法优化/分析DAL

为了稳定,我已经采取暴露IQueryable<T>Expression<...>我的资料库。 这意味着我知道存储库的行为方式,而我的上层可以使用模拟而不用担心“实际的存储库是否支持这个?” (强制集成测试)。

我仍然使用IQueryable<T>等在仓库里的 -但不下来的边界。 我在这里发表了关于这个主题的更多想法 将分页参数放在存储库接口上同样容易。 您甚至可以使用扩展方法(在接口上)添加可选的分页参数,这样具体类只有1个方法可以实现,但调用者可能有2或3个重载。

正如前面的回答所提到的,暴露IQueryable可以让调用者可以使用IQueryable本身,这可能会变得很危险。

封装业务逻辑的首要任务是保持数据库的完整性。

您可以继续公开IList,可能会更改您的参数如下,这就是我们正在做的事情......

public interface ILocationRepository
{
    IList<Location> FindAll(int start, int size);
    IList<Location> FindForState(State state, int start, int size);
    IList<Location> FindForPostCode(string postCode, int start, int size);
}

如果size == -1则返回all ...

替代方式......

如果您仍想返回IQueryable,那么您可以在函数内返回List的IQueryable ..例如......

public class MyRepository
{
    IQueryable<Location> FindAll()
    {
        List<Location> myLocations = ....;
        return myLocations.AsQueryable<Location>;
        // here Query can only be applied on this
        // subset, not directly to the database
    }
}

第一种方法优于内存,因为您将返回较少的数据而不是全部。

我建议使用IEnumerable而不是IList ,使用它你会有更多的灵活性。

通过这种方式,您将能够从Db获得您真正使用的那部分数据,而无需在存储库中完成额外的工作。

样品:

// Repository
public interface IRepository
{
    IEnumerable<Location> GetLocations();
}

// Controller
public ActionResult Locations(int? page)
{
    return View(repository.GetLocations().AsPagination(page ?? 1, 10);
}

这是超级干净和简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM