IDbSetExtensions.AddOrUpdate和关系

Bru*_*nez 5 c# entity-framework

IDbSetExtensions.AddOrUpdate旨在帮助编写无论数据库为空还是已填充的代码.但链接对象需要不同的代码.当数据库为空时,对象还没有ID,您可以通过分配导航属性来链接它们.但是,当对象已存在时,导航属性不起作用,您需要直接设置外键. 在两种情况下,导航属性都适用于代理,但代价是放弃POCO. 编辑:实际上,当两个实体都是旧的时,代理不起作用.

当EF尝试将CountryID设置为0时,此示例在第二个SaveChanges调用中崩溃:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

AddOrUpdate是如何使用的?

Lad*_*nka 9

IDbSetExtensions.AddOrUpdate旨在帮助编写无论数据库为空还是已填充的代码.

AddOrUpdate仅用于Seed代码首次迁移的方法.它不应该在普通代码中使用,因为它有很大的开销和一些限制.开销是对数据库和反射的附加查询.限制是它只检查您正在传递的主体,而不检查其关系.每个关系应该通过单独调用来处理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();
    }
}
Run Code Online (Sandbox Code Playgroud)