Reputation: 5351
I'm creating a database using the code-first way. I have two entities in a 1 to 1 relation, but I don't really know how to instantiate them.
Assume those are my entities:
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;}
}
This is my code:
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();
The relation is already set in my BigFoo object declaration, do I need anyway to set this relation also in the Foo object or it will be automatically assigned?
Thanks all for the help.
EDIT:
I have another doubt: I have my foreign keys named relatedentityIdField.
I have to istantiate also them with the
foo.BigFooId = big.Id;
Or those relations are automatically filled?
ADD EXAMPLE-EDIT
An example can be the relation Nation - President
Every Nation has only one president, and every president is only the president of a Nation.
How can I set this relation using Code-First?
Upvotes: 3
Views: 415
Reputation: 39326
With current model what you really have is two one to many unidirectional relationships. To create a one to one relationship using Code First you must define the PK of the dependent entity as FK of the relationship too (check this link for a detailed explanation).
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;}
}
With this model, you could add data as follows:
If you want to create a new Foo
and Boo
and you want to relate them, you can do the following:
var boo=new Boo();
var foo=new Foo{Boo=boo };
context.Foos.Add(foo);
context.SaveChanges();
You should see Foo
navigation property in your Boo
entity is also filled.
If Foo
already exist and you want to create a new Boo
related with that foo:
You can set the Boo
navigation property in your foo entity:
var foo= context.Find(yourId);
foo.Boo=new Boo();
context.SaveChanges();
Or you can just set the PK/FK property of your new Boo
entity:
var fooId=1;// You already have the Foo id
var boo = new Boo() { FooId = fooId};
context.Boos.Add(boo);
context.SaveChanges();
Whit your model, as I said before, you have two different relationships, so your navigation properties aren't really related. If you want to prove that, add two collections to your entities:
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
}
And later try this:
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();
}
After the last SaveChanges
you will Foo
nav. property in boo
instance and BigFoos
nav property in foo
instance are properly filled.
Notes: I changed your navigation properties to virtual
to meet one of the requirements of Lazy Loading, and I also changed your FK properties as nullables to avoid cycles of cascading delete. Code First did not setup a cascade delete for the optional relationships.
Upvotes: 2