Я нахожусь в процессе перехода на EF6 с Linq To Sql, и у меня есть автоматически сгенерированный объект
public partial class PCU
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public PCU()
{
this.PUs = new HashSet<PU>();
}
public int ID { get; set; }
public int FileNumberID { get; set; }
public Nullable<int> PartnerID { get; set; }
public virtual Company Company { get; set; }
public virtual File File { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PU> PUs { get; set; }
}
где PartnerID — внешний ключ для компании
когда я звоню:
var company = dc.Set<PCU>().FirstOrDefault(c => c.FileNumber == fileNumber).Company;
Однако я получаю объект Null, если я вызываю:
var company = dc.Set<PCU>().Where(c => c.FileNumber == fileNumber).Select(x => x.Company).First();
Он возвращает объект компании, как и ожидалось. У меня включены LazyLoading и ProxyCreation.
Я понимаю, что мог бы использовать:
var company = dc.Set<PCU>().Include(x => x.Company).FirstOrDefault(c => c.FileNumber == fileNumber).Company;
однако, поскольку это существующий код, и у меня такая же проблема для сотен различных объектов, это будет означать огромное количество изменений. Есть ли более простой способ добиться этого?
это ожидаемое поведение ленивой загрузки. Если вы не скажете инфраструктуре сущностей получить связанную сущность, она не будет. Метод FirstOrDefault выполнит запрос, и когда вы попытаетесь получить доступ к объекту Company, он будет нулевым. Но во втором сценарии, когда вы используете company в select и выполняете оператор First, он фактически сообщает ef также загрузить связанные данные. Ссылка на документы
@AamirMasood Это не ожидаемое поведение. Ленивая загрузка позволяет работать без .Include().
Да, отложенная загрузка позволяет работать без .Include(), но если вы на самом деле не используете свойство навигации в Select или любой его вариант, соответствующие данные не будут загружены.
До недавнего времени я тоже понимал Этот. Мы столкнулись с аналогичной проблемой, так как связанные объекты вообще не загружались, когда мы вызывали метод ToList().





Сначала это действительно выглядит так:
dc.Set<PCU>().FirstOrDefault(c => c.FileNumber == fileNumber).Company
похоже на:
dc.Set<PCU>().Where(c => c.FileNumber == fileNumber).Select(x => x.Company).First()
но в случае, если внешний ключ «Компания» имеет значение null при использовании «FirstOrDefault», возврат «Компания», очевидно, вернет значение null.
Во втором случае выбирается действительный FK «Компания» из набора результатов, созданного условием «Где», и возвращается первый из этого набора, поэтому запрос «Где» возвращает «Компания».
Если вы не хотите изменять существующий код, мне кажется, что лучшим решением для вас будет в первую очередь понять, почему у вас есть нулевые внешние ключи в вашей базе данных.
Если это так, как должно быть (например, может существовать нулевая запись «Компания»), вам придется учитывать это в своих запросах, следовательно, изменяя их, чтобы возвращать только существующие записи «Компания».
Редактировать: беру свои слова назад, я пропустил часть "ленивая загрузка включена" ?
В качестве продолжения я считаю, что причиной ошибки является имя ForeignKey (PartnerID), и если бы он был назван «CompanyID», он работал бы нормально.
Мне пришлось стиснуть зубы, и я должен был реализовать
var company = dc.Set<PCU>().Include(x => x.Company).FirstOrDefault(c => c.FileNumber == fileNumber).Company;
где необходимо. Кажется, другого обходного пути нет, кроме переименования столбцов в моей БД (чего я не могу сделать).
Это не ответ на ваш вопрос, а рекомендация. Отложенная загрузка может иметь очень большое влияние на производительность, потому что каждый потребитель ваших сущностей может запросить дополнительные сущности, не зная об этом, и это приведет к большому количеству обращений к базе данных. Я бы порекомендовал вам деактивировать его и использовать
.Include()или.Select()для построения проекций. Кроме того, ваша ленивая загрузка не работает. Пожалуйста, опубликуйте свою конфигурацию контекста, возможно, кто-то другой может помочь вам с этой информацией.