我可以在LINQ to Entities中动态构建where子句吗?

时间:2010-08-27 14:47:38

标签: c# .net linq-to-entities

我正在尝试为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));
}

但是,这不是那么干净。

有什么建议吗?

3 个答案:

答案 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)

有两个值得注意的项目。

  1. LINQ Expression Builder
  2. LinqPadLinQkit是开源的。 PredicateBuilder类演示了如何在Fly上构建Linq Query表达式。
  3. 这些参考资料可能会指导您。

    立即使用,我建议Predicatebuilder。