我有一个表达式返回方法,例如:
public Expression<Func<User, bool>> GetUserPredicate(int userID)
{
return u => u.ID == userID;
}
(在原始代码中,这是我想重用的更长,更复杂的逻辑,以便将其提取出来成为这种方法。)
我可以毫无疑问地在用户查询中使用它:
var user = dbContext.Users
.Where(GetUserPredicate(1))
.Single();
但是我也想在查询其他实体(例如帖子)时使用它:
var post = dbContext.Posts
.Where(p => p.ID == 1)
.Where(p.User => GetUserPredicate(1))
.Single();
但这不起作用。如何实现?
答案 0 :(得分:0)
您可以创建一个通用方法。问题是您需要访问不相关类的属性。但这对于泛型是不可能的,除非泛型类型约束使这些属性可用。想法:在接口中定义所需的属性:
public interface IUserProvider
{
int UserID { get; set; }
}
public class User : IUserProvider ...
public class Post : IUserProvider ...
然后将方法定义为
public Expression<Func<TEntity, bool>> GetUserPredicate<TEntity>(int userID)
where TEntity : IUserProvider
{
return e => e.UserID == userID;
}
答案 1 :(得分:0)
修改:
我的解决方案使用表达式的编译函数。由于EF仅查看表达式树并将其转换为Sql,因此它无法处理编译后的函数,因为它们不是表达式树(请参见下面Filip Corades的评论)。
如果您将我的代码用于可与编译函数一起使用的其他事物,则应该没有任何问题。对于这个问题,这不是正确的答案。
原始答案:
您可以添加使用第一种方法的另一种方法。
public Expression<Func<Post, bool>> GetPostUserPredicate(int userID)
{
Expression<Func<User, bool>> expr = GetUserPredicate(userID);
Func<User, bool> func = expr.Compile();
return post => func(post.User);
}
它的作用是编译用户表达式的功能,并使用它使表达式适合该帖子。您可以这样称呼它(根据您的代码进行调整):
var post = dbContext.Posts
.Where(p => p.ID == 1)
.Where(GetPostUserPredicate(1))
.Single();
您也可以内联而不是使用额外的函数,但是对我来说这有点太混乱了。无论如何,我都会添加它:
var post = dbContext.Posts
.Where(p => p.ID == 1)
.Where(p => GetUserPredicate(1).Compile()(p.User))
.Single();
如果我对编译表达式没有什么遗漏,这应该可以正常工作。
希望这会有所帮助,让我知道它是否有效。
答案 2 :(得分:-2)
也许可以,
public Expression<Func<Object, bool>> GetUserPredicate(int userID)
{
}
否则,如果没有与发布相关的用户标识,则您需要一种新方法。