Запрос анонимного объекта EF возвращает пустые коллекции вместо пустых
Я использую этот трюк для выполнения условных включений с EF. http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx
У меня проблема в том, что любые коллекции, которые не имеют записей, являются нулевыми и не пустыми. Это вызывает головную боль, потому что мне приходится проверять каждую коллекцию, прежде чем я могу просмотреть ее в моем представлении mvc, в противном случае я получаю исключение нулевой ссылки.
Например, коллекция StudentModules будет нулевой. Как я могу превратить его в пустой список в моем запросе? т.е. без необходимости перебирать все это и проверять.
Я могу поместить конструктор в poco для инициализации списка, который исправляет его, но эта коллекция является виртуальным членом в poco (на основе видео EF!) - конечно, это не тот путь?
var query = from module in db.Modules
where module.Id == id
select new
{
module,
QualificationModules = from qualificationModule in module.QualificationModules
where qualificationModule.IsDeleted == false
select new
{
qualificationModule,
qualificationModule.Qualification,
StudentModules = from studentModule in qualificationModule.StudentModules
where studentModule.IsDeleted == false
select new
{
studentModule,
studentModule.Student
}
},
Assessments = (from assessment in module.Assessments
where assessment.IsDeleted == false
select new
{
assessment,
assessment.AssessmentType
}
)
};
var modules = query.AsEnumerable().Select(x => x.module);
return modules.ToList().First();
1 ответ
Исправление отношений запускается, когда объект присоединяется к контексту - либо вручную, вызывая Attach
или когда сущность материализуется в результате запроса (ваш случай).
Он основан на внешних ключах сущности и работает в обоих направлениях:
Если контекст уже содержит сущность
A
с внешним ключомf
к сущностиB
и сущностьB
привязывается к контексту, который имеет первичный ключ с тем же значениемf
как внешний ключ вA
(то есть эти два объекта связаны отношением FK), тогда Entity Framework сделает следующее:- Если
A
имеет свойство ссылки навигации дляB
это назначит прикрепленный объектB
к этой собственности. - Если
B
имеет свойство ссылки навигации дляA
(отношение один-к-одному)A
к этой собственности. - Если
B
имеет свойство коллекции навигации дляA
(отношение один ко многим) это добавитA
к этой коллекции в прикрепленном объектеB
, Если коллекцияnull
он будет создавать экземпляр коллекции перед добавлением.
- Если
Если субъект
B
привязывается к контексту, который имеет внешний ключf
к сущностиA
что контекст уже содержит и имеетf
в качестве первичного ключа EF установит свойства навигации на основе тех же правил, что и выше.
Примечание: тот факт, что исправление отношений основано на внешних ключах (они всегда загружаются при запросе объекта, независимо от того, отображается ли FK как свойство в классе модели или нет), также является причиной того, что исправление отношений делает не применяется и не работает для отношений "многие ко многим", потому что два объекта отношения "многие ко многим" не имеют внешнего ключа.
Теперь, если нет связанных StudentModules
в вашем случае нет StudentModule
объект, который загружается в контекст, и нет ничего, что EF мог бы предназначить для исправления. Имейте в виду, что алгоритм исправления не связан с конкретным запросом и не только фиксирует отношения между сущностями, которые этот запрос материализует, но и учитывает все сущности для исправления, которые контекст уже содержит, независимо от того, как они попали в контекст. Если вы хотите, чтобы экземпляры коллекций создавались как пустые коллекции, EF прошел через все присоединенные родительские объекты StudentModules
и просто создать пустую коллекцию. Нет смысла делать это во время исправления вместо того, чтобы создавать пустые коллекции заранее, до того, как сущности присоединятся к контексту.
Я могу поместить конструктор в poco для инициализации списка, который исправляет его, но эта коллекция является виртуальным членом в poco (на основе видео EF!) - конечно, это не тот путь?
На мой взгляд, это лучшее решение, если вы не хотите иметь null
коллекции в экземплярах вашего модельного класса. Неважно, если коллекция объявлена как virtual
(включить отложенную загрузку) или нет. Тип коллекции не имеет производного типа прокси, только экземпляры, добавленные в коллекцию, являются производными прокси. В обоих случаях вы можете просто использовать StudentModules = new HashSet<StudentModule>();
(или же List
Если вы предпочитаете).