Какой тип объекта возвращает оператор linq? - PullRequest
1 голос
/ 06 марта 2012

Это может быть действительно глупый и очевидный вопрос, но я очень новичок в 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. Я просто список, который я могу перебрать.

Ответы [ 10 ]

11 голосов
/ 06 марта 2012

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

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

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

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

6 голосов
/ 06 марта 2012

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

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

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

4 голосов
/ 06 марта 2012

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

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>

3 голосов
/ 06 марта 2012

Невозможно вернуть анонимные типы из метода (как говорили другие).Создайте конкретный тип и новый.Ваш тип возврата 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();


            }
3 голосов
/ 06 марта 2012

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

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

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

2 голосов
/ 06 марта 2012

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

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

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

2 голосов
/ 06 марта 2012

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

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

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

Как уже отмечалось в некоторых ответах, у вас возникают проблемы с типом возвращаемого значения метода, потому что это анонимный тип.Есть несколько трюков, которые вы можете использовать, чтобы обойти это;в основном они включают в себя определение анонимного типа на сайте вызова 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
1 голос
/ 06 марта 2012

В этом примере вы возвращаете анонимный объект, основанный на типе 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 голос
/ 06 марта 2012

Попробуйте IEnumerable

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

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