2013-07-23 139 views
0

我試圖在實體之間做一個可選的關係,但是我很難找到正確的語法。其實我需要一個0..1到0..2的關係,但我猜測,一旦我找到方法來做0..1到0..1這將是微不足道的。EF代碼第一個0..1到0..1的關係

簡化我有什麼是這樣的:

class Foo 
{ 
    int Id { get; set; } 
    //navigation property 
    virtual Bar Bar { get; private set; } 
} 

class Bar 
{ 
    int Id { get; set; } 

    int? LeftFooId { get; set; } 
    [ForeignKey("LeftFooId")] 
    Foo LeftFoo { get; set; } 

    int? RightFooId{ get; set; } 
    [ForeignKey("RightFooId")] 
    Foo RightFoo { get; set; } 
} 

一個富可連接到零或一個酒吧,絕不會。酒吧可以有一個LeftFoo和一個RightFoo,或者一個或兩個都沒有。如果Foo的Bar屬性沒有被Bar引用,它的Bar屬性應該爲null,並且它應該包含Bar引用它的Bar。

使用上面的代碼,Bar正確引用了Foo,但EF給Foo表一個Bar_Id,並且Bar屬性始終爲空。

我已經嘗試了幾種不同的方法來設置這些實體類,並且我使用了differenct Fluent API調用來完成這項工作,但是我沒有得到想要的結果。

回答

1

試試這個:

public class Foo 
{ 
    public int Id { get; set; } 
    public virtual Bar Bar { get; set; } 
} 

public class Bar 
{ 
    public int Id {get; set;} 
    public virtual Foo LeftFoo {get;set;} 
    public virtual Foo RightFoo {get;set;} 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Bar>() 
       .HasOptiona(b => b.LeftFoo) 
       .WithOptionalDependent() 
       .Map(k = k.MapKey("LeftFooId")); 

    modelBuilder.Entity<Bar>() 
       .HasOptional(b => b.RightFoo) 
       .WithOptionalDependent() 
       .Map(k => k.MapKey("RightFooId")); 
    ... 
} 

結果

Table Screenshot

編輯播種

我會做以下,沒有測試的代碼,但它應該工作:

var bars = new List<Bar>(); 
    bars.Add(new Bar()); 
    bars.Add(new Bar()); 
...//this means as many as you need/want 
    bars.ForEach(b => context.Bars.AddOrUpdate(b)); 
context.SaveChanges(); 

var leftFoos = new List<Foo>(); 
    leftFoos.Add(new Foo()); 
    leftFoos.Add(new Foo()); 
...//this means as many as you need/want 
    leftFoos.ForEach(f => context.Foos.AddOrUpdate(f)); 
context.SaveChanges(); 

var rightFoos = new List<Foo>(); 
    rightFoos.Add(new Foo()); 
    rightFoos.Add(new Foo()); 
...//this means as many as you need/want 
    rightFoos.Foreach(f => context.Foos.AddOrUpdate(f)); 
context.SaveChanges(); 

int i=0; 
foreach(var bar in bars) 
{ 
    bar.LeftFoo = leftFoos.ElementAt(i); 
    bar.RightFoo = rightFoos.ElementAt(i); 
    i++; 
} 
context.SaveChanges(); 

爲簡單起見barsleftFoosrightFoos有相同數目的元素。

+0

這給了我已經有的東西。 FK在那裏,但是當我分配LeftFoo和RightFoo時,那些Foo的Bar_Id保持爲空。我試圖通過添加到OptionalDependent(f => f.Bar)來補救此問題,但是這給了我錯誤:指定的Schema無效。錯誤: (85,6):錯誤0040:類型Bar_LeftFoo未在名稱空間(Alias = Self)中定義。 – Wuolennaj

+0

你確定你沒有做別的事嗎?正如我在本地測試它,它工作。你如何指定'left'和'right'來禁止?你可以發佈嗎? – SOfanatic

+0

我目前在我的種子中做的是製作一堆酒吧的所有fk的null然後保存更改,然後我遍歷所有酒吧,併爲每個空的leftfoo或rightfoo創建一個新的foo,留下Bar屬性爲空,然後我做另一個保存。然後我將新的foo分配給bar(bar.leftfoo = foo)。然後進行更新和保存。 – Wuolennaj

0

我修改這樣的代碼:

class Foo 
{ 
    int Id { get; set; } 
    int? BarId { get; set; } 
    [ForeignKey("BarId")] 
    virtual Bar Bar { get; set; } 
} 

class Bar 
{ 
    int Id { get; set; } 

    int? LeftFooId { get; set; } 
    [ForeignKey("LeftFooId")] 
    Foo LeftFoo { get; set; } 

    int? RightFooId{ get; set; } 
    [ForeignKey("RightFooId")] 
    Foo RightFoo { get; set; } 
} 

我可能是錯的,但一對FK的的自動分配我是不可能的,在從富到酒吧至少:如何將EF知道它應該將FK分配給LeftFoo或RightFoo。所以現在我只是手動執行兩個任務:

Foo myFirstFoo = new Foo(); 
Foo mySecondFoo = new Foo(); 
Bar myBar = new Bar(); 
context.Add(myFirstFoo); context.Add(mySecondFoo); context.Add(myBar); 
context.SaveChanges(); 
myFirstFoo.BarId = myBar.Id; 
myBar.LeftFooId = myFirstFoo.Id; 
mySecondFoo.BarId = myBar.Id; 
myBar.RightFooId = mySecondFoo.Id; 
context.Update(myFirstFoo); context.Update(mySecondFoo); context.Update(myBar); 
context.SaveChanges(); 

這似乎工作,但我希望它可以做得更好。

0

嘗試使您的屬性變爲虛擬並使用POCO代理(使用Create而不是新的...)。這將確保側屬性的自動更新。即將Foo分配給Bar時,POCO代理會將相應的Bar分配給Foo,但是,這應該是主要問題:如果將Bar分配給Foo,您會得到什麼結果?你想自動分配哪個屬性,剩下的權利?註釋Bar屬性[InverseProperty(「...」)]以表明這一點,並考慮您可能需要其他關係的Foo類型Bar的另一個屬性。 希望這可以幫助