Могу ли я динамически создать предложение where в LINQ to Entities? - PullRequest
2 голосов
/ 27 августа 2010

Я пытаюсь динамически построить запрос LINQ для LINQ to Entities, чтобы избежать повторения одной и той же функции дважды.

Вот что я пытаюсь сделать:

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 'Invoke' не поддерживается в LINQ to Entities

Я потенциально мог бы сделать это:

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 ]

1 голос
/ 27 августа 2010

Вы можете объединить два синтаксиса 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;

Надеюсь, это укажет вам правильное направление!

1 голос
/ 27 августа 2010

Вы можете сделать это, но вам нужно использовать, например, 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 (или подобное).

0 голосов
/ 27 августа 2010

На этом есть два заметных проекта.

  1. Построитель выражений LINQ и
  2. LinqPad LinQkit с открытым исходным кодом. Класс PredicateBuilder демонстрирует, как создавать выражения Linq Query на лету.

эти ссылки могут помочь вам.

Для немедленного использования я предлагаю Predicatebuilder.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...