c# - Entity Framework Core - 使用接口作为参数的表达式树
问题描述
我将非常感谢以下情况的一些帮助。我有以下课程:
public class Product : IHasPrice
{
public string Title { get; set; }
public int Price { get; set; }
public string CustomerId { get; set; }
}
public interface IHasPrice
{
int Price { get; set; }
}
public class ProductProvider
{
public ProductProvider()
{
}
public IEnumerable<Product> GetByCustomer(string customerId, Expression<Func<IHasPrice, bool>> predicate = null)
{
using (var db = new ApplicationDbContext())
{
var queryable = db.Products.Where(p => p.CustomerId == customerId);
if (predicate != null)
{
return queryable.Where(predicate).ToList();
}
else
{
return queryable.ToList();
}
}
}
}
我希望能够以ProductProvider
您只能按客户选择的方式使用,但您也可以以您喜欢的任何方式过滤价格(并且只能过滤价格)。此示例不起作用,因为queryable.Where
需要带有 typeof 的参数Expression(Func(Product, bool))
。有没有办法做到这一点,或者我必须在过滤价格之前将数据提取到内存中?
解决方案
由于IQueryable<out T>
interface 是covariant,因此传递的 lambda 表达式可以直接与Where
方法一起使用:
var query = queryable.Where(predicate);
唯一的问题是现在结果查询的类型是IQueryable<IHasPrice>
. 您可以将其转回IQueryable<Product>
使用Queryable.Cast
方法:
var query = db.Products.Where(p => p.CustomerId == customerId);
if (predicate != null)
query = query.Where(predicate).Cast<Product>(); // <--
return query.ToList();
经过测试并使用最新的 EF Core 2.2(在某些早期版本中可能会失败)。
另一种解决方案是通过“调用”将其转换Expression<Func<IHasPrice, bool>>
为预期的:Expression<Func<Product, bool>>
var query = db.Products.Where(p => p.CustomerId == customerId);
if (predicate != null)
{
var parameter = Expression.Parameter(typeof(Product), "p");
var body = Expression.Invoke(predicate, parameter);
var newPredicate = Expression.Lambda<Func<Product, bool>>(body, parameter);
query = query.Where(newPredicate);
}
return query.ToList();
推荐阅读
- scala - 在使用 scala 的版本化配置的情况下,如何将解析与验证分开?
- sql-server-2008 - EclipseLink:ManyToOne 映射到 SINGLE_TABLE 继承策略失败
- cordova - 离子本地通知 TypeError: Object(...) is not a function
- azure-devops - 如何在 Azure DevOps 中按用户和日期报告记录的任务时间?
- git - git 裸存储库、工作树和跟踪分支
- sql-server - 如何从触发器内的其他表中读取未提交的数据
- makefile - make: /bin/sh: 找不到命令
- c - 需要帮助 我的图书馆项目有成员问题
- mysql - 如何在 SQL Percentile Window 函数上添加条件?
- java - 单击箭头时未调用 JComboBox setPopupVisible