IDbSetExtensions.AddOrUpdate is meant to help write code that works the same whether the database is empty or populated. But linking objects needs different code. When the database is empty, objects don't have IDs yet and you link them by assigning the navigational property. When the objects already exist, however, navigational properties don't work and you need to set the foreign keys directly. Navigational properties do work for proxies in both cases, at the cost of forfeiting POCOs. Edit: Actually, proxies don't work when both entities are old.
This sample crashes in the second SaveChanges call, when EF tries to set CountryID to 0:
public class Country
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
}
public class Person
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual int CountryID { get; set; }
public virtual Country Country { get; set; }
}
public class Context : DbContext
{
public DbSet<Person> Person { get; set; }
public DbSet<Country> Country { get; set; }
}
class Program
{
static void Foo()
{
using (var db = new Context())
{
//var c = new Country();
var c = db.Country.Create();
c.Name = "usa";
db.Country.AddOrUpdate(x => x.Name, c);
//var p = new Person();
var p = db.Person.Create();
p.Name = "billg";
p.Country = c;
db.Person.AddOrUpdate(x => x.Name, p);
db.SaveChanges();
}
}
static void Main()
{
Database.SetInitializer<Context>(new DropCreateDatabaseAlways<Context>());
Foo();
Foo();
}
}
How is AddOrUpdate used?
IDbSetExtensions.AddOrUpdate is meant to help write code that works the same whether the database is empty or populated.
AddOrUpdate
is meant to be used only in Seed
method of code first migrations. It is not supposed to be used in normal code because it has big overhead and some limitations. Overhead is additional query to database and reflection. Limitation is that it checks only the main entity you are passing but not its relations. Each relation is supposed to be handled by separate call to AddOrUpdate
:
static void Foo()
{
using (var db = new Context())
{
var c = new Country() {Name = "abc"};
db.Country.AddOrUpdate(x => x.Name, c);
var p = new Person()
{
Name = "me",
CountryID = c.ID,
Country = c
};
db.Person.AddOrUpdate(x => x.Name, p);
db.SaveChanges();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With