开发者

Can I dynamically build a where clause in LINQ to Entities?

I'm trying to dynamically build a LINQ query for LINQ to Entities so that I can av开发者_开发百科oid repeating the same function twice.

Here is what I'm trying to do:

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));
}

The filter parameter is throwing this exception:

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities

I could potentially do this:

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));
}

But, that is not as clean.

Any suggestion?


You can combine the two LINQ syntaxes:

private IQueryable<IUser> BuildQuery(IQueryable<IUser> users, string userName)
{
    users = users.Where(u => u.UserName == userName);
    return users;
}

Then when you call it:

var query = from u in this.BuildQuery(this.adapter.Users, userName)
            select u;

Hopefully this will point you in the right direction!


You can do this, but you need to use, e.g., Expression<Func<..., not just 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()
}

Note that interfaces won't translate to L2E. So you must use User, not IUser (or the like).


There are two notable projects on this.

  1. LINQ Expression Builder, and
  2. LinqPad's LinQkit which is open source. The PredicateBuilder class demonstrates how to build Linq Query expressions on the Fly.

these references might guide you.

For your immediate use, I suggest Predicatebuilder.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜