2012-03-06 3 views
1

Это может быть действительно глупый и очевидный вопрос, но я очень новичок в Linq. В моем классе доступа к данным слоя у меня есть этот метод:Какой объект возвращает оператор linq?

static public ? GetAllUrls() 
     { 



      using (MonitoredUrlsEntities mu = new MonitoredUrlsEntities()) 
      { 


       var query = from urlTbl in mu.UrlLists 
          join histTbl in mu.Histories on 
          urlTbl.ID equals histTbl.UrlID 
          select new 
          { 
           urlTbl.Url, 
           urlTbl.UrlTitle, 
           urlTbl.UrlType, 
           urlTbl.Frequency, 
           urlTbl.Active, 
           urlTbl.LastChangeDate, 
           urlTbl.LastCheckDate, 
           histTbl.DateRun, 
           histTbl.HashValue 
          }; 

        return query.ToList(); 


      } 

вопросительный знак там, потому что я понятия не имею, какой тип объекта через LINQ оператор возвращает. Я просто список, который я могу пройти.

+0

Зависит от заявления, но в целом IQueryable. – Jason

ответ

3

не может возвратить анонимные типы из метода (как уже говорили другие).Создайте конкретный тип и новый из них. Ваш возвращаемый тип IEnumerable<YourType>, как показано ниже:

// NOTE: I do not know the actual types of these properties, YMMV 
public sealed class UrlHistoryList 
{ 
    public string Url { get; set; } 
    public string UrlTitle { get; set; } 
    public string UrlType { get; set; } 
    public int Frequency { get; set; } 
    public bool Active { get; set; } 
    public DateTime LastChangeDate { get; set; } 
    public DateTime LastCheckDate { get; set; } 
    public DateTime DateRun { get; set; } 
    public int HashValue { get; set; } 
} 

static public IEnumerable<UrlHistoryList> GetAllUrls() 
     { 



      using (MonitoredUrlsEntities mu = new MonitoredUrlsEntities()) 
      { 


       var query = from urlTbl in mu.UrlLists 
          join histTbl in mu.Histories on 
          urlTbl.ID equals histTbl.UrlID 
          select new UrlHistoryList 
          { 
           Url = urlTbl.Url, 
           UrlTitle = urlTbl.UrlTitle, 
           UrlType = urlTbl.UrlType, 
           Frequency = urlTbl.Frequency, 
           Active = urlTbl.Active, 
           LastChangeDate = urlTbl.LastChangeDate, 
           LastCheckDate = urlTbl.LastCheckDate, 
           DateRun = histTbl.DateRun, 
           HashValue = histTbl.HashValue 
          }; 

        return query.ToList(); 


      } 
+0

это замечательно! создать класс и вернуть его из метода. – Gandarez

+0

Я получаю «Не могу инициализировать тип« ChangeDetection.UrlHistoryList »с инициализатором коллекции, потому что он не реализует« System.Collections.IEnumerable ». Любые идеи, почему бы это сказать? – broke

+3

@broke: Поскольку Джесси случайно дал вам синтаксис для инициализатора коллекции, а не для инициализатора объекта. Это должно быть '... new UrlHistoryList {Url = urlTbl.Url, UrlTitle = urlTbl.UrlTitle ...' –

1

Попробуйте IEnumerable

Если вы уронили .ToList(), было бы IQueryable

2

Обычно оператор LINQ возвращает IEnumerable/IQueryable, таким образом, по этой причине вы можете использовать .ToList(). В вашем случае вы возвращаете список из-за .ToList().

Если удалить ToList(), я бы ваше возвращение как IEnumerable, если все, что вы хотите сделать, это цикл по результатам

6

вы используете анонимный тип в выражении LINQ - и, как документация гласит:

Вы не можете объявить поле, свойство, событие или тип возвращаемого метода как имеющий анонимный тип.

http://msdn.microsoft.com/en-us/library/bb397696.aspx

+1

И чтобы обойти это, создайте тип со свойствами/полями, которые вы выбираете и возвращаете (список), которые вместо этого. –

3

Ну, что это List<T> где T некий анонимный тип, который вы не можете сказать, в собственном коде (анонимные типы приведены отвратительные имена).

Это сделано намеренно таким образом; обычно бывает ошибкой распространять анонимные типы вне местных применений.

Вы должны сделать конкретный тип, вместо использования анонимного типа. Назовите его Foo. Тогда ваш тип возврата будет List<Foo>.

+1

* «Анонимным типам даются невыразимые имена» * - например, «Волдеморт»? –

4

Он возвращает список анонимного типа, и вы не можете вернуть анонимный тип из метода (возможно, если вы используете динамический, вы можете, но это беспорядок). Вместо использования анонимного типа создать новый класс со всеми свойствами и заполнить его в проекции:

var query = from urlTbl in mu.UrlLists 
      join histTbl in mu.Histories on 
       urlTbl.ID equals histTbl.UrlID 
      select new YourNewType 
      { 
       Url = urlTbl.Url, 
       UrlTitle = urlTbl.UrlTitle, 
       UrlType = urlTbl.UrlType, 
       Frequency = urlTbl.Frequency, 
       Active = urlTbl.Active, 
       LastChangeDate = urlTbl.LastChangeDate, 
       LastCheckDate = urlTbl.LastCheckDate, 
       DateRun = histTbl.DateRun, 
       HashValue = histTbl.HashValue 
      }; 

Теперь ваш метод может вернуть IEnumerable<YourNewType>

+1

Или это может быть «объект». – jason

+1

@ Джейсон: Но в таком случае вы полностью потеряете доступ к внутренним данным. –

+0

А? Нет. Вы можете использовать или использовать отражение. – jason

2

возвращает IQueryable<T> где T анонимной объект, определенный в select new части запроса.

В конце концов он возвращается как List<T>

Метод подписи, вероятно, следует: public static List<dynamic> GetAllUrls() , потому что static public ? GetAllUrls() является недопустимым.

1

В этом примере вы возвращаете анонимный объект базы по типу IQueryable<T> так может просматривать список как этот

foreach (var item in query) 
{ 
    //you could access to each attribute of the object like this 

    string url = item.Url 
    string urlTittle = item.UrlTittle 
} 
1

Как отметили некоторые ответы, у вас возникли проблемы с возвращаемым типом метода, поскольку это анонимный тип. Есть несколько трюков, которые вы могли бы использовать, чтобы обойти это; они в основном связаны с определением анонимного типа на сайте вызова GetAllUrls, определяя GetAllUrls в качестве общего метода и позволяя выводам типа компилятора делать все остальное.

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

foreach (var url in mu.UrlLists) 
    foreach (var history in url.Histories) 
    { 
     var obj = new {  
          url.Url,  
          url.UrlTitle,  
          url.UrlType,  
          url.Frequency,  
          url.Active,  
          url.LastChangeDate,  
          url.LastCheckDate,  
          history.DateRun,  
          history.HashValue  
         }; 
     // do something with obj 
    } 

или просто

foreach (var url in mu.UrlLists) 
    foreach (var history in url.Histories) 
     //do something with url and history 
11

Как уже отмечалось, результаты данного конкретного запроса вовлечь в анонимный тип. Поэтому вы не можете аннотировать метод как возвращающий точный тип локальной переменной, потому что вы не можете ввести имя этого типа, потому что у него нет имени; это то, что означает «анонимный».

Вы можете сказать, что метод возвращает IEnumerable<object> или IEnumerable или object или даже dynamic, но, вероятно, лучше всего сделать это, чтобы сделать запрос возвращает последовательность номинального типа в первую очередь.

В более общем плане: как и другие отметили, запрос обычно имеет какую-то IEnumerable или IQueryable типа на практике. Однако важно понимать, что выражение LINQ не обязательно имеет какой-либо конкретный тип. LINQ реализуется как синтаксическое преобразование , а не semantic трансформация. Когда вы говорите:

var query = from c in customers select c.Name; 

компилятор переводит, что слепо в:

var query = customers.Select(c=>c.Name); 

Тип query является то, что метод Select происходит, чтобы вернуться. Это может быть int! Это почти наверняка не так, потому что это было бы немой, но если какой-то извращенный человек решил сделать метод под названием Select, который возвращает int, тогда запрос будет иметь тип int.

Как оказалось, я просто такой извращенный человек; Я приведу пример использования LINQ для манипулирования целых чисел здесь:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/07/query-transformations-are-syntactic.aspx

+1

Спасибо для информации! Ваш блог скалы кстати. – broke

Смежные вопросы