不同的上下文可以创建相同的对象吗?

时间:2013-01-03 16:37:22

标签: c#-4.0 entity-framework-4.1

我正在将Entity Framework 4.4用于现有的.NET 4.0应用程序。它有一些模块化,我需要每个架构有一个DbContext。例如

public class AnimalContext : DbContext // animal schema
{
    public IDbSet<Dog> Dogs { get; set; }

    public IDbSet<Cat> Cats { get; set; }
}

public class FruitContext : DbContext // fruit schema
{
    public IDbSet<Apple> Apples { get; set; }

    public IDbSet<Pear> Pears { get; set; }
}

某些实体引用不同架构中的实体,例如

public class Dog
{
    public Apple Apple { get; set; }
}

无论如何确保不同上下文创建的实体是相同的吗?即。

var animals = new AnimalContext()
var fruits = new FruitContext()

var dog = animals.Dogs.First();
var apple = fruits.Apples.First(x => x == apple)

// and object.ReferenceEquals(apple, dog.Apple)

2 个答案:

答案 0 :(得分:0)

由不同上下文创建的实体(即使是相同上下文类型的不同实例)也不会相同。

恕我直言,您必须自己处理它,不允许AnimalContext创建FruitContext中定义的对象实例 - 在您的案例Apple实体中并将Apple分配给{{1}在Dog加载后,您需要在FruitContext上公开AppleId属性。这可能通过在Dog事件处理程序中处理内部连接而以某种方式自动化,但它可以减慢对象加载速度,并且可以使您的上下文紧密耦合。

您可以在ObjectContext.ObjectMaterialized属性或狗上使用NotMapped属性,或在Apple类或Ignore属性的Apple属性中使用Apple映射定义。如果AnimalContext具有反向导航属性Apple,则您还必须忽略Dog上的Dog

答案 1 :(得分:0)

为了确保由不同DbContext创建的实体相同,必须共享一个可以通过ObjectContext构造函数传递的公共DbContext

使用Code First方法创建公共ObjectContext的方法是通过DbModelBuilder - 访问其中一种方法的推荐方法是通过覆盖继承类的OnModelCreating(DbModelBuilder)方法来自DbContext

例如:

public class MasterContext : DbContext
{
    public MasterContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
    }

    public static implicit operator ObjectContext(MasterContext obj)
    {
        if (obj == null)
        {
            throw new ArgumentNullException("obj");
        }

        var adapter = (IObjectContextAdapter)obj;

        return adapter.ObjectContext;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Dog>();
        modelBuilder.Entity<Cat>();
        modelBuilder.Entity<Apple>();
        modelBuilder.Entity<Pear>();
    }
}

public class AnimalContext : DbContext
{
    public AnimalContext(ObjectContext context)
        : base(context, false)
    {
    }

    public IDbSet<Dog> Dogs { get; set; }

    public IDbSet<Cat> Cats { get; set; }
}

public class FruitContext : DbContext
{
    public FruitContext(ObjectContext context)
        : base(context, false)
    {
    }

    public IDbSet<Apple> Apples { get; set; }

    public IDbSet<Pear> Pears { get; set; }
}

//...
var master = new MasterContext("my connection")
var animals = new AnimalContext(master)
var fruits = new FruitContext(master)

var dog = animals.Dogs.First();
var apple = fruits.Apples.First(x => x == apple)

// Passes
Debug.Assert(object.ReferenceEquals(apple, dog.Apple))

这里需要注意的重要一点是,OnModelCreating中的MasterContext必须注册所有奴隶DbContexts中使用的每种类型(你可以明显地将其添加到自动注册所有内容中需要)。