EntityFramework Code首先添加1到1个数据

时间:2016-02-18 16:01:19

标签: c# entity-framework foreign-keys

我使用代码优先方式创建数据库。 我有两个1对1关系的实体,但我真的不知道如何实例化它们。

假设这些是我的实体:

public class Foo
{
    [Key]
    public int Id {get;set;}
    [ForeignKey("BigFoo")]
    public int BigFooId {get;set;}
    public virtual BigFoo BigFoo {get;set;}
}

public class BigFoo
{
    [Key]
    public int Id {get;set;}
    [ForeignKey("Foo")]
    public int FooId{get;set;}
    public virtual Foo Foo {get;set;}
}

这是我的代码:

Foo foo = new Foo();
foo = db.Foo.Add(foo);

BigFoo big = new BigFoo {Foo = foo, FooId = foo.Id};
big = db.BigFoo.Add(big);

//HERE is my doubt
//I don't know if I have to add the relation also in the Foo object
//Do i need the following code?

//foo.BigFoo = big;
//foo.BigFooId = big.Id;
//db.Foo.Attach(foo);
//var entry = db.Entry(foo);
//entry.Property(x => x.BigFoo).IsModified = true;

db.SaveChanges();

该关系已在我的BigFoo对象声明中设置,我是否还需要在Foo对象中设置此关系,否则它将自动分配?

感谢大家的帮助。

编辑:

我有另一个疑问:我的外键名为relateddentityIdField。

我必须用

来解释它们
foo.BigFooId = big.Id;

或者那些关系是自动填充的?

添加示例 - 编辑

一个例子可以是关系 Nation - President

每个国家只有一位总统,每位总统都只是一个国家的总统。

如何使用Code-First设置此关系?

1 个答案:

答案 0 :(得分:2)

使用当前模型,您真正拥有的是两个一对多的单向关系。要使用Code First创建一对一的关系,您必须将依赖实体的PK定义为关系的FK(请查看此link以获取详细说明)。

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

  public virtual Boo Boo {get;set;}
}

public class Boo
{
  [Key, ForeignKey("Foo")]
  public int FooId{get;set;}

  public virtual Foo Foo {get;set;}
}

使用此模型,您可以按如下方式添加数据:

  1. 如果您想要创建新的FooBoo并想要关联它们,可以执行以下操作:

    var boo=new Boo();
    var foo=new Foo{Boo=boo };
    context.Foos.Add(foo);
    context.SaveChanges();
    
  2. 您应该看到Foo实体中的Boo导航属性也已填充。

    1. 如果Foo已经存在,并且您想要创建与该foo相关的新Boo

      您可以在foo实体中设置Boo导航属性:

      var foo= context.Find(yourId);
      foo.Boo=new Boo();
      context.SaveChanges();
      

      或者您可以设置新Boo实体的PK / FK属性:

       var fooId=1;// You already have the Foo id
       var boo = new Boo() { FooId = fooId};
       context.Boos.Add(boo);
       context.SaveChanges();
      
    2. 按照我之前的说法,使你的模型发白,你有两种不同的关系,所以你的导航属性并没有真正相关。如果您想证明这一点,请向您的实体添加两个集合:

      public class Foo
      {
          [Key]
          public int Id {get;set;}
          [ForeignKey("BigFoo")]
          public int? BigFooId {get;set;}
          public virtual BigFoo BigFoo {get;set;}
          public virtual ICollection<BigFoo> BigFoo{get;set;}// Add this property
      }
      
      public class BigFoo
      {
          [Key]
          public int Id {get;set;}
          [ForeignKey("Foo")]
          public int? FooId { get; set; }
          public virtual Foo Foo {get;set;}
          public virtual ICollection<Foo> Foos{get;set;}// Add this property
      }
      

      后来试试这个:

      using (var context=new MyContext())
      {
          var foo = new Foo();
          context.Foos.Add(foo);
          context.SaveChanges();
      
          var boo = new BigFoo() { FooId = foo.Id};
      
          context.Boos.Add(boo);
          context.SaveChanges();
       }
      

      在最后SaveChanges之后,您将Foo导航。 boo实例中的属性和BigFoos实例中的foo nav属性已正确填充。

      注意:我将导航属性更改为virtual以满足Lazy Loading的要求之一,并且我还将您的FK属性更改为nullables以避免级联循环删除。 Code First没有为可选关系设置级联删除。