LINQ Entities не розпізнає метод


116

Я отримую таку помилку при спробі зробити запит linq:

LINQ для Entities не розпізнає метод "Boolean IsCharityMatching (System.String, System.String)", і цей метод не може бути переведений у вираз зберігання.

Я читав багато попередніх питань, коли люди отримують однакову помилку, і якщо я правильно це розумію, це тому, що LINQ для Entities вимагає, щоб весь вираз запиту linq був переведений на серверний запит, і тому ви не можете викликати зовнішній метод в цьому. Я ще не зміг перетворити свій сценарій у щось, що працює, і мій мозок починає танути, тож я сподівався, що хтось може направити мене в правильному напрямку. Ми використовуємо Entity Framework і модель специфікацій (і я новачок для обох).

Ось код, який використовує специфікацію:

ISpecification<Charity> specification = new CharitySearchSpecification(charityTitle, charityReference);

charities = charitiesRepository.Find(specification).OrderBy(p => p.RegisteredName).ToList();

Ось вираз linq:

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    return p => p.IsCharityMatching(this.charityName, this.charityReference);
}

Ось метод IsCharityMatching:

public bool IsCharityMatching(string name, string referenceNumber)
{
    bool exists = true;

    if (!String.IsNullOrEmpty(name))
    {
        if (!this.registeredName.ToLower().Contains(name.ToLower()) &&
            !this.alias.ToLower().Contains(name.ToLower()) &&
           !this.charityId.ToLower().Contains(name.ToLower()))
        {
            exists = false;
        }
    }

    if (!String.IsNullOrEmpty(referenceNumber))
    {
        if (!this.charityReference.ToLower().Contains(referenceNumber.ToLower()))
        {
            exists = false;
        }
    }

    return exists;
}

Повідомте мене, якщо вам потрібна додаткова інформація.

Велике дякую,

Аннелі


перевірити цю відповідь
Еранга

Перевірте це також, дякую!
annelie

1
Було б добре побачити, як ви користуєтесь, Find()як використовуєте IsSatisfied()всередині нього.
Еліссон

Відповіді:


124

Як ви зрозуміли, Entity Framework насправді не може запустити код C # як частину його запиту. Він повинен бути в змозі перетворити запит у фактичний оператор SQL. Для того, щоб це працювало, вам доведеться реструктурувати вираз запиту в вираз, з яким Entity Framework може працювати.

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    string name = this.charityName;
    string referenceNumber = this.referenceNumber;
    return p => 
        (string.IsNullOrEmpty(name) || 
            p.registeredName.ToLower().Contains(name.ToLower()) ||
            p.alias.ToLower().Contains(name.ToLower()) ||
            p.charityId.ToLower().Contains(name.ToLower())) &&
        (string.IsNullOrEmpty(referenceNumber) ||
            p.charityReference.ToLower().Contains(referenceNumber.ToLower()));
}

1
коли сумніваєтесь, пошукайте це: stackoverflow.com/questions/2352764/…
Кріс Хейз

2
Повернення побудованого Expression<Func<T,type>>- дуже приємний підхід до цього.
Travis J

Як би ви використовували це в виразі LINQ? Я хотів би зробити щось подібне як умовне повторне використання Де, але я борюся з його реалізацією.
Зоргарат

4
EDIT: ніколи не буде, це буде:context.Where(IsSatisfied())
Zorgarath

Ключова частина: "Entity Framework насправді не може запустити код C # як частина запиту".
Альпер

1

Я отримав таку ж помилку в цьому коді:

 var articulos_en_almacen = xx.IV00102.Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

це була саме помилка:

System.NotSupportedException: 'LINQ для сутностей не розпізнає метод' Існує булева система (System.Predicate`1 [conector_gp.Models.almacenes_por_sucursal]) ', і цей метод не може бути переведений у вираз магазину.'

Я вирішив так:

var articulos_en_almacen = xx.IV00102.ToList().Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

Я додав .ToList () перед моєю таблицею, це роз'єднати код Entity та linq і уникати перекладу мого наступного виразу linq

ПРИМІТКА. Це рішення не є оптимальним, оскільки уникайте фільтрації об'єктів, а просто завантажує всю таблицю в пам'ять


1
Здебільшого це найпростіше рішення, але щоб не завантажувати весь об'єкт, я зазвичай роблю анонімний вибір перед .ToList () саме тим, що мені потрібно ... xx.Select (x => new {x.Id, x.DateTimeUpdate }) ToList () Вибрати (х => новий {x.Id, DateTimeUpdate = x.DateTimeUpdate.ToString ( "дд / мм / рррр".)}).
Diógenes

0

Якщо хтось шукає відповідь VB.Net (як я був спочатку), ось це:

Public Function IsSatisfied() As Expression(Of Func(Of Charity, String, String, Boolean))

Return Function(charity, name, referenceNumber) (String.IsNullOrWhiteSpace(name) Or
                                                         charity.registeredName.ToLower().Contains(name.ToLower()) Or
                                                         charity.alias.ToLower().Contains(name.ToLower()) Or
                                                         charity.charityId.ToLower().Contains(name.ToLower())) And
                                                    (String.IsNullOrEmpty(referenceNumber) Or
                                                     charity.charityReference.ToLower().Contains(referenceNumber.ToLower()))
End Function

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.