我正在尝试为LINQ to Entities动态构建LINQ查询,以便我可以避免重复两次相同的函数。
这是我正在尝试做的事情:
private IUser GetOrUpdateUser(Predicate<IUser> filter, Func<IIdentityProvider, UserRecord> fetch)
{
var user = (from u in this.adapter.Users
where filter(u)
select u).SingleOrDefault();
if (user == null)
{
// User not found. Add him.
user = this.adapter.AddUser(fetch(this.idenityProvider));
}
else if (user.IsExpired)
{
// User found, but expired. Update him.
this.adapter.UpdateUser(user, fetch(this.idenityProvider));
}
return user;
}
protected IUser GetUserByNetworkId(string username)
{
return GetOrUpdateUser(
u => u.NetworkId == username,
i => i.GetUserByNetworkId(username));
}
protected IUser GetUserByEmail(string email)
{
return GetOrUpdateUser(
u => u.Email == email,
i => i.GetUserByEmail(email));
}
filter
参数抛出此异常:
LINQ to Entities
不支持LINQ表达式节点类型“Invoke”
我可能会这样做:
protected IUser GetUserByNetworkId(string username)
{
return GetOrUpdateUser(
from u in this.adapter.Users
where u.NetworkId == username
select u,
i => i.GetUserByNetworkId(username));
}
protected IUser GetUserByEmail(string email)
{
return GetOrUpdateUser(
from u in this.adapter.Users
where u.Email == email
select u,
i => i.GetUserByEmail(email));
}
但是,这不是那么干净。
有什么建议吗?
答案 0 :(得分:1)
您可以执行此操作,但您需要使用Expression<Func<...
,而不仅仅是Func<...
。
Expression<Func<User, Bool>> MakePredicate(int id)
{
return u => u.Id == id;
}
void DoStuff()
{
Expression<Func<User, Bool>> pred = MakePredicate(123);
User u = Context.Users.Where(pred).Single()
}
请注意,接口不会转换为L2E。因此,您必须使用User
,而不是IUser
(或类似内容)。
答案 1 :(得分:1)
您可以组合使用两种LINQ语法:
private IQueryable<IUser> BuildQuery(IQueryable<IUser> users, string userName)
{
users = users.Where(u => u.UserName == userName);
return users;
}
然后当你打电话时:
var query = from u in this.BuildQuery(this.adapter.Users, userName)
select u;
希望这会指出你正确的方向!
答案 2 :(得分:0)
有两个值得注意的项目。
这些参考资料可能会指导您。
立即使用,我建议Predicatebuilder。