2015-02-16 2 views
4

Я пытался найти свой путь с EF в течение последних нескольких дней/недель. В настоящее время я немного застрял в обработке внешних ключей, в этом случае у меня есть таблица, в которой есть два FK для себя (никаких вопросов о моем дизайне БД, никаких вопросов, так как это только та ситуация, с которой я столкнулся, нет никаких шансов изменить структуру базы данных).Внешние ключи в инфраструктуре Entity 6.1.2

Я уменьшил свой код на этом примере ниже, в котором я использую одной таблицы, описываемого класса Foo:

class Foo 
{ 
    public int ID { get; set; } 

    public string Data { get; set; } 

    public int firstFkID { get; set; } 

    public int secondFkID { get; set; } 

    [ForeignKey("firstFkID")] 
    public virtual Foo firstFk { get; set; } 

    [ForeignKey("secondFkID")] 
    public virtual Foo secondFk { get; set; } 
} 

Мой DbContext производный класс:

class EFFKContext : DbContext 
{ 
    public EFFKContext(string connectionString) : base(connectionString) { } 

    public virtual DbSet<Foo> Foo { get; set; } 
} 

И конечно код, в котором я использую все это:

static void Main(string[] args) 
{ 
    SqlConnectionStringBuilder cnStrBuilder = new SqlConnectionStringBuilder() 
    { 
     DataSource = "(local)", 
     InitialCatalog = "EF_FK", 
     IntegratedSecurity = true 
    }; 

    EFFKContext context = new EFFKContext(cnStrBuilder.ConnectionString); 

    Foo foo = context.Foo.Find(3); 

    Foo fFoo = foo.firstFk; 

    Foo sFoo = foo.secondFk; 
} 

Когда я компилирую это, нет никаких проблем, но во время выполнения я получаю следующее сообщение об ошибке:

An unhandled exception of type 'System.InvalidOperationException' occurred in >EntityFramework.dll

Additional information: Unable to determine the principal end of an association >between the types 'RF_EF_FK.Foo' and 'RF_EF_FK.Foo'. The principal end of this >association must be explicitly configured using either the relationship fluent >API or data annotations.`

Может кто-нибудь объяснить, почему я получаю эту ошибку, что это точно значит, и указать направление, в котором Мне придется изменить свой код, чтобы заставить его вести себя так, как я этого хочу?

Который может получить объекты, на которые указывают два FK.

Я попытался следующие:

  • Добавление дополнительных навигационных свойств, возвращающих коллекции, хотя это не дает искомое решение. Также отношения не являются отношениями «один ко многим», поэтому это даже не кажется правильным.

  • Я также попытался добавить некоторый код API Fluent, но опять же это не обеспечило мне решение, в котором я нуждаюсь.

Хотя я пробовал вышеуказанные вещи, вполне возможно, что я что-то пропустил. Любая помощь более чем приветствуется!


Edit:

, продолжая свои поиски, чтобы решить эту проблему, я обнаружил, что добавив следующую строку в моем контексте класса позволило бы решить проблему FK.

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{   
    modelBuilder.Entity<Foo>().HasOptional(f => f.secondFk).WithMany().HasForeignKey(f => f.secondFkID); 
    modelBuilder.Entity<Foo>().HasOptional(f => f.firstFk).WithMany().HasForeignKey(f => f.firstFkID); 
} 

Теперь при загрузке объект из базы данных, мне нужно использовать Include функции включают в себя соответствующие объекты сразу, или использовать следующий, чтобы загрузить его позже:

context.Entry(sFoo).Reference("firstFk").Load(); 

Все еще не уверены, будь то это путь.

+0

На какой линии вы получаете исключение ??? – Blaatz0r

+0

Исключение выдается при загрузке объекта – RFerwerda

+1

Возможный дубликат [Что делает основной конец ассоциации в отношении 1: 1 в структуре Entity] (http://stackoverflow.com/questions/6531671/what-does-principal- end-of-an-association-mean-in-11-relationship-in-entity-fr) – kjbartel

ответ

2

В связи с тем, что никакие другие ответы, чем один из Жениш Radadiya были представлены, я не буду размещать свои собственные выводы, как ответ прямо сейчас.

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

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{   
    modelBuilder.Entity<Foo>().HasOptional(f => f.secondFk).WithMany().HasForeignKey(f => f.secondFkID); 
    modelBuilder.Entity<Foo>().HasOptional(f => f.firstFk).WithMany().HasForeignKey(f => f.firstFkID); 
} 

Теперь при загрузке объекта из базы данных мне нужно использовать функции Включить, чтобы соответствующие объекты сразу, или использовать следующий, чтобы загрузить его позже:

context.Entry(sFoo).Reference("firstFk").Load(); 

Еще не уверен, что это путь.

1

Возможно, вам понадобится сделать одно поле равным нулю. Я не уверен в этом.

Вы можете использовать Fluent api вместо этого, чтобы подготовить отношение модели.

class Foo 
{ 
    public int ID { get; set; } 

    public string Data { get; set; } 

    public int firstFkID { get; set; } 

    public int secondFkID { get; set; } 

    //[ForeignKey("firstFkID")] <- remove this while using fluent api 
    public virtual Foo firstFk { get; set; } 

    //[ForeignKey("secondFkID")] <- remove this while using fluent api 
    public virtual Foo secondFk { get; set; } 
} 

Попробуйте это.

public class FooConfiguration : EntityTypeConfiguration<Foo> 
{ 
    public FooConfiguration() 
    { 
     this.HasKey(x => x.ID); 

     this.HasOptional(f => f.firstFk) 
      .WithOptionalDependent(f => f.secondFk); 
    } 
} 

Я также нашел одну родственную StackOverflow нить =>here

+0

Спасибо за ответ, хотя он не дает мне решение/направление, которое я ищу. – RFerwerda

Смежные вопросы