Упростите это свойство для использования в предикате - PullRequest
2 голосов
/ 09 марта 2012

У меня много Accounts, у каждой учетной записи также могут быть дочерние учетные записи.Так что мой способ узнать, является ли учетная запись root, благодаря значению в свойстве ParentId.
Так что оказалось, что мой код имеет такие вещи во многих местах: .Where(acc => acc.ParentId == 0), поэтому я подумал о создании свойстваэто выглядит так:

public bool IsRootAccount
{
    return a.ParentId == 0;
}

Вроде работает, компилируется, но при запуске я получаю следующее исключение:

Load operation failed for query 'GetAccounts'. The specified type member 'IsRootAccount' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

Есть простойКак я могу достичь того, чего хочу?

Я также думал о создании чего-то, что вернуло бы Expression<Func<Account, bool>> без удачи.

Редактировать: моя попытка использования свойства IsRootAccount была для того, чтобы использовать что-то вроде этого .Where(acc => acc.IsRootAccount)

Ответы [ 2 ]

1 голос
/ 09 марта 2012

Очень простой способ предоставить эту функцию - использовать метод расширения.

Попробуйте что-то вроде этого:

public static class AccountEx
{
    public static IQueryable<Account> WhereIsRootAccount(
            this IQueryable<Account> source)
    {
        return source.Where(acc => acc.ParentId == 0);
    }
}

Тогда вы бы заменили каждое использование .Where(acc => acc.ParentId == 0) на * 1007.*.

Преимущество этого подхода состоит в том, что он работает с EF и обеспечивает быстрый способ запроса корневых учетных записей.Если вам нужно изменить определение учетной записи root, у вас также есть только одно место для внесения изменений.И это не загрязняет ваш Account класс ненужным кодом.

Надеюсь, это поможет.


На основании вашего комментария попробуйте следующее:

public static class AccountEx
{
    public static EntityQuery<Account> WhereIsRootAccount(
            this EntityQuery<Account> source)
    {
        return source.Where(acc => acc.ParentId == 0);
    }
}

Так как EntityQuery<> поддерживается *1020*, он все равно должен работать нормально.

0 голосов
/ 09 марта 2012

Вот кое-что, что я нашел, но хотел бы посмотреть, есть ли что-нибудь лучше.
Я понимаю, что EF не знает, как преобразовать мой предикат в SQL из-за моего свойства. Поэтому я не могу сделать это:

Context.Load(Context.GetAccountsQuery().Where(acc => acc.IsRootAccount), ParentAccountsArrived, null);  

но я могу выполнить фильтрацию по своему свойству, как только результаты вернутся с сервера:

public void LoadParentAccounts()
{
    Context.Load(Context.GetAccountsQuery(), ParentAccountsArrived, null);  
}
void ParentAccountsArrived(LoadOperation<Account> lo)
{
    foreach (var account in lo.Entities.Where(acc => acc.IsRootAccount))
    {
        ParentAccounts.Add(account.Name);
    }
}   

Это путь? Есть ли проблемы с производительностью с этим изменением?

...