Подтвердить что ты не робот

EF4 code-first: определение отношений объектов, внешних ключей

< RANT_MODE >

EF-код-первый подход предназначен для экономии времени, но пока я видел только примеры игрушек и потратил часы, пытаясь понять, как я могу заставить его генерировать db, который я хочу. Но все же надеясь, что момент Эврики: -)

< RANT_MODE/" >

На вопросы!

Виртуальные и конкретные свойства

Я пытаюсь понять, как EF отображает и восстанавливает отношения объектов. Когда следует помечать свойство как virtual, а когда нет? (Как в public Person Owner { get; set; } vs. public virtual Person Owner { get; set; }.) В десятках примеров кода сначала я видел, что они, кажется, используют эти взаимозаменяемо, без особого объяснения. Я знаю, что свойства навигации (public virtual ICollection<Person> Owners { get; set; }) должны быть virtual, чтобы сделать возможной ленивую загрузку (правильно..?), Но как это применимо в мире не-коллекций?

Связи объектов и внешние ключи

Мне не удалось найти информацию о том, следует ли включать поле внешнего ключа (public int OwnerId { get; set; }) в дополнение к интересующему мне свойству "main" (public Person Owner { get; set; }). Я старался не делать этого, и EF любезно добавила в столбец int Owner_Id в моей таблице, казалось бы, понимая, что я хотел достичь.

В Соглашения для первого кода (раздел "Внешние ключи" ) команда EF упоминает, что "обычно включать свойство внешнего ключа в зависимый конец отношения", и что "Code First теперь выведет, что любое свойство с именем" "(т.е. OwnerId) [...] с тем же типом данных, что и первичный ключ, представляет собой внешний ключ для отношения". То есть. если у меня есть оба EF, они будут знать, что они связаны.

Но считается ли хорошей практикой явно указывать такие свойства, содержащие FKs, помимо самих "посторонних объектов"?

Посторонние предметы, внешние ключи - продолжение

Как я уже упоминал выше, даже если у меня есть только public Person Owner { get; set; } в моем объекте (скажем Event), таблица Events будет содержать столбец Owner_Id, автоматически добавленный EF. Что еще, после извлечения у меня будет доступ к свойствам Owner.

Однако рассмотрим следующий сценарий. У меня есть два класса:

public class Account
{
    public int Id { get; set; }
    public Person Owner { get; set; }
}

public class OpenIdAccount : Account
{
    public string Identifier { get; set; }
}

Я хочу, чтобы они были связаны с TPT. Это означает ручное сопоставление:

modelBuilder.Entity<Account>().MapHierarchy(a => new
{
    a.Id, 
    Owner_Id = a.Owner.Id
}).ToTable("Account");

modelBuilder.Entity<OpenIdAccount>().MapHierarchy(a => new
{
    a.Id,
    a.Identifier
}).ToTable("OpenIdAccount");

Как вы можете заметить, я попытался воссоздать то, что EF делает с моим столбцом Owner_Id. Однако при поиске myAccountInstanceFromDb.Owner имеет значение null. Почему это? Как сообщить EF, что он должен сделать свою магию и заполнить мое свойство Owner?

Указатели, указатели

Я буду очень благодарен, если вы сможете прояснить вышеизложенное, дошел до того, что действительно хотел узнать ответы, но не смог прочитать еще одну статью, которая просто демонстрирует еще один игрушечный пример того, как легко играть с EF, Тем не менее, если у вас есть исчерпывающая обновленная ссылка на мозг EF, пожалуйста, также разместите ссылки.

Заранее благодарим за ваше время!

4b9b3361

Ответ 1

Виртуальные и конечные свойства:

Это не имеет никакого отношения к коду, это тема EF и POCOs: когда у вас есть POCOs, вы теряете кучу поддержки EF для своих свойств навигации, и вы можете выбрать их, сделав их виртуальными. Это позволяет EF создавать прокси-сервер во время выполнения и предоставлять вам поддержку, переопределяя свойства nav в этом прокси-классе. Этими оповещениями являются Уведомление об изменении, Фиксация отношений и Лестная загрузка.

Lazy Loading работает одинаково для свойств навигации Collection и non Collection. Также считается хорошей практикой всегда отмечать ваши свойства навигации как виртуальные.

Ассоциация внешних ключей или независимые ассоциации

EF3.5 не поддерживает FK в ассоциациях и делает их скрытыми (a.k.a Независимые ассоциации). EF4 начинает поддерживать FK в ассоциациях (a.k.a Foreign Key Association). В зависимости от того, какой из них вам нравится, вы можете явно включать или не включать свойства FK, но определенно хорошая практика явно указывать свойства FK в дополнение к свойствам навигации, поскольку она дает вам максимальную гибкость для работы с вашими объектами.

При извлечении myAccountInstanceFromDb.Owner имеет значение null. Почему это? Как я могу сказать EF, что он должен сделать свою магию и заполнить мою собственность владельца?

Конечно, вы не отметили его как виртуальную, поэтому Lazy Loading не поддерживается, но вы явно не загружаете или не загружаете его. Чтобы разрешить это, используйте либо виртуальное ключевое слово, и пусть EF ленивый загрузит его для вас или использует метод Include, чтобы он мог загрузить его во время материализации всего объекта.

Скалярные свойства и свойства навигации

Скалярные свойства - это свойства, значения которых буквально содержатся в сущности и соответствуют столбцам таблицы (например, Account.Id).
Свойства навигации - это просто указатели на связанные объекты. Например, объект Account имеет свойство Owner, которое позволит приложению перемещаться с учетной записи Владельцу, которому принадлежит эта учетная запись.
Итак, вернемся к вашему вопросу, все, что вам нужно сделать, это указать свойство навигации как virtual Person Owner и опционально указать свойство FK как int OwnerId, и вам хорошо идти.

Ответ 2

маркировка свойства virtual приводит к ложному вызову связанных объектов

вам не нужно добавлять поле внешнего ключа public Person Owner {get; задавать; } добавит отображение внешнего ключа