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

17

& л;

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

& л; RANT_MODE / & gt;

На вопросы!

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

Я пытаюсь понять, как 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 любезно добавила в таблицу столбца с именем 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, пожалуйста, также разместите ссылки.

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

    
задан Dav 26.11.2010 в 02:33
источник
  • Первый код предназначен для экономии времени, если вы не слишком заинтересованы в базе данных. Если вам нужен минутный контроль, лучший способ - создать его в SQL Management Studio и сначала использовать базу данных для генерации вашего EDMX. –  DamienG 28.11.2010 в 19:10
  • Угадайте, что это зависит от взгляда на то, что «минутный контроль» :-) Лично мне не нужны имена столбцов и столбцов, но я хочу, чтобы база данных была эффективной и хорошо разработана с технической точки зрения. который я бы не боялся работать в будущем, если я, например. необходимо запросить его напрямую. Но ваш вопрос определенно важен, и я согласен - CF предоставляет нам мощные инструменты, но также требует некоторого контроля. –  Dav 28.11.2010 в 22:56
  • Жаль, что я не смог бы проголосовать за это больше, чем раз, в частности, разглагольствования. Я не уверен, как работает код по соглашению, если на самом деле соглашения не публикуются каким-либо ссылочным способом. Здесь я немного конвенциональный трюк, а другой там. Очень болезненный. –  Ralph Shillington 16.12.2010 в 04:23
  • Спасибо Ральфу, ты должен сказать, что благодаря некоторым полезным людям здесь, в SO, я думаю, что был самым худшим и начал наслаждаться EF4. Точка на условностях, объясняемая в полном объеме, по-прежнему действительна, большинство из того, что я теперь знаю, это части из разных сообщений ScottGu и других блогов, с трудом собранных методом проб и ошибок. Надеюсь, что это многое улучшится, когда он войдет в RTM! –  Dav 20.12.2010 в 14:21
  • Любил этот пост. Я согласен с вами, я только начал свой путь на этой неделе на EF4 + SQL CE4 и увидел каждый болезненный шаг, который вы здесь описываете, нет ни одной публикации, которая бы давала вам широкие снимки, просто множество подобных игрушечных образцов. –  Nestor 27.04.2011 в 09:38

2 ответа

9

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

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

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

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

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

  

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

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

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

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

ответ дан Morteza Manavi 26.11.2010 в 05:54
  • @Morteza, спасибо за то, что вы снова ответили на мои основные вопросы - вы действительно являетесь чемпионом знаний! «Считается хорошей практикой всегда отмечать ваши свойства навигации как виртуальные» - прочитав ваше объяснение, я понимаю это сейчас. Вопрос в том, в чем разница между равным свойством и навигационным свойством - достаточно ли просто иметь свойство навигации в объекте или его нужно резервировать с помощью простого свойства? –  Dav 26.11.2010 в 09:42
  • Другими словами, если у меня есть учетная запись, принадлежащая Лицу, чтобы определить взаимосвязь между ними, выполните следующие действия: 1) укажите свойство int OwnerId и свойство виртуального владельца навигации, или 2) укажите свойство Владелец лица или 3) укажите свойство виртуального владельца навигации? –  Dav 26.11.2010 в 09:44
  • PS: Я прочитал объяснение в MSDN, но я все еще не уверен, что свойство навигации может стоять на своем собственном уровне или если ему нужна поддержка из явного свойства, либо ссылаясь на другой объект / его FK. –  Dav 26.11.2010 в 09:50
  • Нет проблем и спасибо :) Да, навигационная способность может стоять сама по себе, см. мой обновленный ответ на эту тему. –  Morteza Manavi 26.11.2010 в 19:11
  • @Morteza, вы снова сохранили этот день. Когда вы говорите мне указатели, мир внезапно становится намного понятнее и понятнее. Я мог только пожелать хотя бы некоторых статей по EF следовать вашему пути объяснения вещей. Тема закрыта с моей точки зрения - увидимся на следующей :-) –  Dav 26.11.2010 в 23:20
0

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

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

    
ответ дан Rony 26.11.2010 в 02:39
  • Спасибо, что подтвердили это! Однако, как вы можете видеть из .MapHierarchy, мне нужно сделать это вручную, потому что я использую стратегию TPT. –  Dav 26.11.2010 в 09:47