LINQ To Entities не распознает индекс массива - PullRequest
1 голос
/ 02 декабря 2011

У меня есть следующая функция в моем коде

  public List<string> GetpathsById(List<long> id)
        {

            List<string> paths = new List<string>();
            for (int i = 0; i < id.Count; i++)
            {

                Presentation press = context.Presentations.Where(m => m.PresId == id[i]).FirstOrDefault();
                paths.Add(press.FilePath);
            }
            return paths;
        }

Но когда я пытаюсь это сделать, компилятор получает такую ​​ошибку.

LINQ to Entities does not recognize the method 'Int64 get_Item(Int32)' method, and this method cannot be translated into a store expression.

Затем я пытаюсь сделать что-то подобное и всеотлично работает.

  public List<string> GetpathsById(List<long> id)
        {
             long x;
            List<string> paths = new List<string>();
            for (int i = 0; i < id.Count; i++)
            {
                x = id[i];
                Presentation press = context.Presentations.Where(m => m.PresId == x).FirstOrDefault();
                paths.Add(press.FilePath);
            }
            return paths;
        }

Так вот интересно, почему?Я не могу получить ответ на это поведение в моей голове.Кто-нибудь может объяснить этот парадокс?

Ответы [ 2 ]

2 голосов
/ 02 декабря 2011

В этом нет волшебства: деревья выражений переводятся в запросы SQL, что понимают реляционные базы данных. Вы можете сделать почти все в дереве выражений. К сожалению, не все операции реализованы. Рассмотрим следующий пример:

Presentation press = context
   .Presentations
   .Where(m => SomeCustomFunctionThatUsesUnmanagedPInvokeCode(m.PresId))
   .FirstOrDefault();

Что вы ожидаете от сгенерированного SQL-запроса?

Так обстоит дело с индексаторами массивов. Они не могут быть переведены в запросы SQL.

Как говорится, в вашем случае следующее может быть немного проще:

public List<string> GetpathsById(List<long> id)
{
    return
        (from p in context.Presentations
         where id.Contains(p.PresId)
         select p.FilePath
        ).ToList();
}

Метод .Contains будет переведен в предложение SQL IN. Это позволяет избежать отправки нескольких запросов SQL в базу данных, как это делается в вашем примере на каждой итерации.

1 голос
/ 02 декабря 2011

Этот вопрос был задан другим пользователем, поэтому это должно быть школьное задание.

По сути, я дал этот же ответ другому пользователю.

Его нельзя сопоставить с типом или функцией SQL.

Все, что вы хотите сделать в этом коде, можно сделать, просто используя список и повторяя его несколько иным способом.

Следующий бит кода сделает все, что вам нужно.

public List<string> GetpathsById(List<long> id)  
{
    List<string> paths = new List<string>();  
    foreach(long aa in id)  
    {  
        Presentation press = context.Presentations.Where(m => m.PresId == aa).FirstOrDefault();  
        paths.Add(press.FilePath);  
    }  
    return paths;  
}  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...