Я пишу модели Entity Framework Code-First без существующей базы данных. В своих объектах я объявил свои внешние отношения один-ко-многим как явно, так и как свойства навигации с отложенной загрузкой, например:
UserRecord класс
[Key]
public long ID { get; set; }
public virtual List<WorkItemRecord> WorkItemsAuthored { get; set; } // authored work items
WorkItemRecord класс:
[Key]
public long ID { get; set; }
public long AuthorID { get; set; } // user ID of the author
public virtual UserRecord Author { get; set; } // navigation lazy-loaded property
Идея сохранения внешнего ключа как идентификатора, так и свойства навигации в классе WorkItemRecord заключается в том, что в тех случаях, когда мне просто нужен фактический идентификатор пользователя, лежащий в основе, я могу ссылаться на него напрямую, не вызывая свойство и не вызывая другого Поиск в БД.
Проблема в том, что когда EF создает схему базы данных, она не связывает их вместе. Он создает отдельные столбцы: AuthorID
и UserRecord_ID
Сначала я подумал, может быть, это потому, что моя собственность была Author
, а не User
. Однако даже когда я явно указал это с помощью атрибута свойства ...
[ForeignKey("Author")]
public long AuthorID { get; set; }
public virtual UserRecord Author { get; set; }
... У меня все еще остаются те же два столбца в сгенерированной схеме.
Также попытался поставить декоратор на другое свойство ...
public long AuthorID { get; set; }
[ForeignKey("AuthorID")]
public virtual UserRecord Author { get; set; }
... и получить тот же результат.
Я бы хотел избежать Fluent API, если это возможно, но я открыт для этого, если у меня не будет других решений.
Любые идеи?
Благодарность!
ОБНОВЛЕНИЕ
Спасибо за помощь! Fluent API работал нормально, но исправить аннотацию данных с помощью декоратора обратных свойств оказалось намного проще. Окончательное решение:
UserRecord класс:
public long ID { get; set; }
public virtual List<WorkItemRecord> WorkItemsAuthored { get; set; }
WorkItemRecord класс:
public long ID { get; set; }
[ForeignKey("Author")]
public long AuthorUserID { get; set; }
[InverseProperty("WorkItemsAuthored")]
public virtual UserRecord Author { get; set; }
У Microsoft также есть статья, посвященная этой конкретной проблеме:
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships
2 ответа
Ссылочного свойства должно быть достаточно, чтобы EF распознал отношение «один ко многим», но есть ли у вас свойство навигации в классе UserRecord
?
public class UserRecord
{
/* other properties */
public virtual List<WorkItemRecord> WorkItemsAuthored { get; set; }
}
Возможно, есть небольшая деталь, из-за которой EF не распознает внешний ключ.
ОБНОВЛЕНИЕ: Попробуйте InverseProperty
в классе UserRecord
, как показано ниже:
[InverseProperty("WorkItemsAuthored")]
public virtual UserRecord Author { get; set; } // navigation lazy-loaded property
Из «Programming Entity Framework: Code First», написанного Джулией Лерман и Роуэном Миллером:
... вы можете столкнуться со сценарием, в котором существует несколько отношений между сущностями. В этих случаях Code First не сможет определить, какие свойства навигации совпадают.
Я предполагаю, что класс UserRecord
имеет более одного List<WorkItemRecord>
.
В вашем классе DbContext
добавьте это в свой метод OnModelCreating
.
modelBuilder.Entity<Book>() //Guessing at your class name
.HasRequired(e => e.Author)
.WithMany(e => e.Books)
.HasForeignKey(e => e.AuthorID);
Это усилит ограничение.
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.