2016-04-15 3 views
3

Я пытаюсь получить результаты с помощью LINQ в WPF на Visual Studio 2015 с использованием Entity Framework 6 (EF). Результаты должны появиться в одном ListView для тестов сотрудника. У меня есть два объекта EF: DrugTests и AlcoholTests. В моем проекте у меня есть некоторые модели просмотра, чтобы их сопоставить с: DrugTestViewModel и AlcoholTestViewModel, оба получены из интерфейса ITestViewModel.Linq AddRange() для объектов, полученных из интерфейса

Две виртуальные машины имеют много свойств, а также имеют свои собственные уникальные (отсюда необходимость в двух объектах). Я использую LINQ, чтобы вернуть Task<ObservableCollection<ITestViewModel>>, первая выборка из DrugTests лица:

var query = (from dt in context.DrugTests 
      .Where(x => x.employeeID.Equals(employeeId)) 
      select new DrugTestViewModel 
      { 
       EmployeeId = dt.employeeID, 
       TestType = "Drug", 
       OrderedDate = dt.orderedDate, 
       // set other properties 
      } 
).ToList(); 

Тогда я пытаюсь добавить в запрос с помощью этого:

query.AddRange(from at in context.AlcoholTests 
        .Where(x => x.employeeID.Equals(employeeId)) 
       select new AlcoholTestViewModel 
       { 
        EmployeeId = at.employeeID, 
        TestType = "Alcohol", 
        // set other properties... 
       } 
    ); 

Это дает следующее исключение на AddRange() :

Аргумент 1: не может конвертировать из 'System.Linq.IQueryable<MySolution.ViewModel.AlcoholTestViewModel>' в 'System.Collections.Generic.IEnumerable<MySolution.ViewModel.DrugTestViewModel>'

Что я делаю неправильно?

+0

Ваша проблема заключается в том, что 'query' является' List ', и вы пытаетесь добавить к нему' AlcoholTestViewModel'. – juharr

+4

Попробуйте заменить 'ToList()' на 'ToList ()' –

+0

Спасибо, @IvanStoev. Это исправило это! Не возражаете ли вы бросить это в ответ, и я приму это? – Alex

ответ

1

Проблема в том, что переменная типа query равна List<DrugTestViewModel>, тогда как она вам нужна, чтобы она имела тип List<ITestViewModel>. Так IQueryable<T> ковариантен, вы можете добиться того, что просто указав явно нужный тип при вызове ToList как этот

var query = (...).ToList<ITestViewModel>(); 
+0

Спасибо, @IvanStoev.Что означает «ковариант» в этом контексте? – Alex

+3

Это означает, что вы можете обрабатывать 'IQueryable ' как 'IQueryable '. –

0

В результате в контексте ... это запрос, следовательно, ошибка IQuerable Добавление объявления .ToList() в конец вашего запроса linq возвращает список, поддерживающий IEnumerable.

Ваш первый фрагмент кода содержит .ToList() ваша вторая отсутствует.

+0

Лучше использовать 'AsEnumerable' и не создавать промежуточный список. – juharr

+0

Спасибо, @juharr. См. Обновление к исключению. Это не даст мне возможность для 'ToList()' во втором запросе; имеет '.ToString()' но не 'ToList()' – Alex

+0

@Alex Вы поставили круглые скобки вокруг вашего запроса? – juharr

2

Немного поздно, но я хотел бы поделиться этим другое решение. Я хотел бы использовать Concat таким образом:

var query=... 
var query2=.. 
var result= query.AsEnumerable<ITestViewModel>().Concat(query2); 

Таким образом, вы сохранить отложенное выполнение в случае, если вам не нужно материализовать результата пока нет.

+0

Другое хорошее решение. Спасибо, @octavioccl :) – Alex

+1

добро пожаловать;) – octavioccl

+1

Интересная идея. Но 'Cast' throws '* LINQ to Entities поддерживает только листинг EDM-примитивов или типов перечисления. *" Так что это должно быть 'AsQueryable'. Который также выдает исключение, если два конкретных класса имеют разные поля: «* DbUnionAllExpression требует аргументов с совместимой коллекцией ResultTypes. *» :( –