EF4 code-first: определение объектных отношений, внешние ключи - PullRequest
17 голосов
/ 26 ноября 2010

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

На вопросы!

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

Я пытаюсь понять, как EF отображает и получает объектные отношения.Когда следует помечать свойство как virtual, а когда нет?(Как в public Person Owner { get; set; } против 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, по-видимому, понимая, чего я хотел достичь.

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

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

Иностранные объекты,внешние ключи - продолжение

Как я упоминал выше, даже если в моем объекте только 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 является нулевым.Это почему?Как мне сказать EF, что он должен творить свою магию и заполнять мое свойство Owner?

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

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

Заранее благодарим вас за потраченное время!

Ответы [ 2 ]

9 голосов
/ 26 ноября 2010

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

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

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

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

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

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

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

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

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

0 голосов
/ 26 ноября 2010

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

вам не нужно добавлять поле внешнего ключа государственный владелец задавать; } добавит отображение внешнего ключа

...