EF Code First 0..1到0..1的关系

时间:2013-07-23 12:37:30

标签: ef-code-first entity-framework-5

我正在尝试在实体之间建立可选关系,但我无法找到正确的语法。实际上我需要一个0..1到0..2的关系,但是我猜测一旦找到了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; }
}

Foo可以连接到零或一个Bar,永远不会更多。一个Bar可以有一个LeftFoo和一个RightFoo,或者一个或两个都没有。如果没有Bar引用,则Foo的Bar属性应该为null,并且它应该包含在Bar引用它时引用它的Bar。

使用Bar上方的代码正确引用Foo,但EF为Foo表提供了一个Bar_Id,Bar属性始终为null。

我已经尝试了几种不同的方法来设置这些实体类,并且我使用了不同的Fluent API调用来实现这一功能,但是我没有得到想要的结果。

3 个答案:

答案 0 :(得分: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具有相同数量的元素。

答案 1 :(得分: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是不可能的,至少从Foo到Bar: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();

这似乎有效,但我希望它可以做得更好。

答案 2 :(得分:0)

尝试将您的属性设置为虚拟并使用POCO代理(使用Create而不是new ...)。这将确保侧面属性的自动更新。即当将Foo分配给Bar时,POCO代理会将相应的Bar分配给Foo,但是......这应该是主要问题:如果将一个Bar分配给Foo,您会有什么期望?您希望自动分配哪个属性,在左边?注释Bar属性[InverseProperty(“...”)]来表明这一点,并想一想你可能需要另一个关系中另一个类型为Bar的属性。 希望这有帮助