В Поддержка членов типа в LINQ-to-Entities? Я пытался объявить свойство класса для запроса в LINQ, что привело к возникновению некоторых проблем.Здесь я выложу код внутри реализации в надежде на некоторую помощь для преобразования его в запрос.
У меня есть класс Quiz
, который содержит коллекцию Question
s, каждый из которых классифицированв соответствии с QuestionLevel
... мне нужно определить, является ли тест «открытым» или «закрытым», что осуществляется посредством внешнего объединения на уровнях вопросов и подсчета вопросов на каждом уровне по сравнению стаблица максимальных значений.Вот код, дословно:
public partial class Quiz
{
public bool IsClosed
{
get
{
// if quiz has no questions, it's open
if (this.Questions.Count() == 0) return false;
// get a new handle to the EF container to do a query for max values
using (EFContainer db = new EFContainer())
{
// we get a dictionary of LevelName/number
Dictionary<string, int> max = db.Registry
.Where(x => x.Domain == "Quiz")
.ToDictionary(x => x.Key, x => Convert.ToInt32(x.Value));
// count the number of questions in each level, comparing to the maxima
// if any of them are less, the quiz is "open"
foreach (QuestionLevel ql in db.QuestionLevels)
{
if (this.Questions.Where(x => x.Level == ql).Count() < max["Q:Max:" + ql.Name])
return false;
}
}
// the quiz is closed
return true;
}
}
}
, так что вот моя еще не работающая попытка:
public static IQueryable<Quiz> WhereIsOpen(this IQueryable<Quiz> query)
{
EFContainer db = new EFContainer();
return from ql in db.QuestionLevels
join q in query on ql equals q.Questions.Select(x => x.Level)
into qs
from q in qs.DefaultIfEmpty()
where q.Questions.Count() < db.Registry
.Where(x => x.Domain == "Quiz")
.Where(x => x.Key == "Q:Max" + ql.Name)
.Select(x => Convert.ToInt32(x.Value))
select q;
}
не удается выполнить учетную запись при объединении, жалуясь:
Неверно указан тип одного из выражений в предложении соединения.Ошибка вывода типа при вызове 'GroupJoin'
Я все еще пытаюсь выяснить это.
* обновление I *
ах.глупое я.
join q in query on ql equals q.Questions.Select(x => x.Level).Single()
еще один блокпост:
Указанное выражение LINQ содержит ссылки на запросы, связанные с различными контекстами.
thisиз-за нового контейнера, который я создаю для максимального поиска;поэтому я подумал перефакторировать вот так:
public static IQueryable<Quiz> WhereIsOpen(this IQueryable<Quiz> query)
{
EFContainer db = new EFContainer();
IEnumerable<QuestionLevel> QuestionLevels = db.QuestionLevels.ToList();
Dictionary<string, int> max = db.Registry
.Where(x => x.Domain == "Quiz")
.ToDictionary(x => x.Key, x => Convert.ToInt32(x.Value));
return from ql in QuestionLevels
join q in query on ql equals q.Questions.Select(x => x.Level).Single()
into qs
from q in qs.DefaultIfEmpty()
where q.Questions.Count() < max["Q:Max:" + ql.Name]
select q;
}
но я не могу заставить выражение скомпилировать ... мне нужно преобразовать QuestionLevels в IQueryable (но приведение не работает, производяисключения времени выполнения).
* обновление II *
Я нашел решение проблемы приведения, но теперь я вернулся к исключению "разные контексты".grr ...
return from ql in QuestionLevels.AsQueryable()
* обновление (предложение Кирка) *
, так что теперь у меня есть это, которое компилируется, но генерирует исключение времени выполнения:
public static IQueryable<Quiz> WhereIsOpen(this IQueryable<Quiz> query)
{
EFContainer db = new EFContainer();
IEnumerable<string> QuestionLevels = db.QuestionLevels.Select(x => x.Name).ToList();
Dictionary<string, int> max = db.Registry
.Where(x => x.Domain == "Quiz")
.ToDictionary(x => x.Key, x => Convert.ToInt32(x.Value));
return from ql in QuestionLevels.AsQueryable()
join q in query on ql equals q.Questions.Select(x => x.Level.Name).Single()
into qs
from q in qs.DefaultIfEmpty()
where q.Questions.Count() < max["Q:Max:" + ql]
select q;
}
, который я затем называю так:
List<Product> p = db.Quizes.WhereIsOpen().Select(x => x.Component.Product).ToList();
с результирующим исключением:
Этот метод поддерживает инфраструктуру LINQ to Entities и не предназначен дляиспользовать прямо из вашего кода.