【问题标题】:Is it a good practice to pass IQueryable as parameter in a Service layer method?在服务层方法中将 IQueryable 作为参数传递是一种好习惯吗?
【发布时间】:2012-05-14 03:20:09
【问题描述】:

我有一个具有 3 层 UIService LayerRepository 的 ASP.NET 应用程序。

我必须对数据库中的产品实施搜索功能ProductRepository 是我的 repository 类,从数据库中获取所有 products 的方法的签名是:

IQueryable<Product> GetAllProducts();

因此从我的服务层我使用:

IProductRepository _ProductRepository = new ProductRepository(); 

IQueryable<Product> products = _ProductRepository.GetAllProducts();

如果我想过滤IQueryable&lt;Product&gt; products,例如选择那些 price > 100 的产品或只选择 color = "yellow" 的产品。

所以我想知道,而不是在ProductRepository 中创建方法,例如:

IQueryable<Product> GetAllProductsByColor(int colorId)

我想知道在我的服务层中创建一组接受IQueryable&lt;Product&gt;作为参数并直接在那里执行过滤的方法是否是一个好习惯:

IQueryable<Product> FilterProducts(IQueryable<Product> products, Dictionary<string, object> filters)

其中Dictionary&lt;string, string&gt; 表示具有 (propertyName, value) 的集合。

此解决方案的优点是,如果我必须应用多个过滤器,我只需传递已过滤的 IQueryable&lt;Product&gt;,而不是每次都获取过滤后的产品集之间的交集。

这是一种好习惯(只要我保持上下文打开)还是多层架构模式不“允许”?

【问题讨论】:

    标签: asp.net parameters filter iqueryable service-layer


    【解决方案1】:

    我会说这取决于提供 IQueryable 实现的内容。在大多数情况下,您冒着允许 IQueryable 的用户执行以下任一操作的风险:1) 过滤未编入索引的字段(因此,当您有大表时,如果有的话,数据库层会存储数据库层),或者 2) 执行任意 IQueryable对数据库造成巨大负载的操作(例如 GroupBy、Join 等)。

    假设您同意 1,为了防止 2) 我通常允许用户通过 IEnumerable&lt;Product&gt; LoadProducts(Predicate&lt;Product&gt; filter) 方法加载对象,然后我将其转换为 IQueryable 上的 Where;这隐藏了其他 IQueryable 方法,但允许完全灵活地仅用于过滤目的。

    【讨论】:

    • 感谢您的回答!我总是从存储库返回 IQueryable 以允许延迟执行。我的服务层总是返回 IEnumerable。你可以用一些例子来解释你使用 Predicate 的技术吗?
    • 假设你有如下方法:IEnumerable&lt;Product&gt; LoadProducts(Expression&lt;Func&lt;Product, bool&gt;&gt; filter),那么你可以将它实现为return myQueryable.Where&lt;Product&gt;(filter),你可以用lambda-expression调用它:IEnumerable&lt;Product&gt; results = LoadProducts(p =&gt; p.Color == Colors.Red)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    相关资源
    最近更新 更多