我正在尝试在实体之间建立可选关系,但我无法找到正确的语法。实际上我需要一个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调用来实现这一功能,但是我没有得到想要的结果。
答案 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"));
...
}
<强> 结果 强>
编辑播种
我会做以下操作,没有测试代码,但它应该工作:
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();
为简单起见bars
,leftFoos
和rightFoos
具有相同数量的元素。
答案 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的属性。 希望这有帮助