Entity framework EntityFramework CTP5更改跟踪

Entity framework EntityFramework CTP5更改跟踪,entity-framework,poco,entity-framework-ctp5,Entity Framework,Poco,Entity Framework Ctp5,我试图使用CTP5 DBContext来复制与EntityObject相同的行为,以进行更改跟踪。考虑一下电影和导演。一部电影只有一个导演,每个导演有多部电影 var movie = new Movie(); movie.Name = "ABCD"; ctx.Movies.Add(movie);//ctx.Movies.AddObject(movie); movie.Director = new Director() {

我试图使用CTP5 DBContext来复制与EntityObject相同的行为,以进行更改跟踪。考虑一下电影和导演。一部电影只有一个导演,每个导演有多部电影

var movie = new Movie();
            movie.Name = "ABCD";
            ctx.Movies.Add(movie);//ctx.Movies.AddObject(movie); 
            movie.Director = new Director() { Name = "dir1" };
            var existingDirector = ctx.Directors.Where(a => a.Name == "dir2").FirstOrDefault();
            movie.Director = existingDirector;
            ctx.SaveChanges();
如果我使用EntityObject运行此代码,则在跟踪更改时,此代码将创建一个新的控制器“dir1”。如果使用CTP5DBContext生成器运行此代码,则不会创建新的控制器“dir1”。我将电影和导演对象中的属性都更改为虚拟。下面是代码

public partial class Director
{
    public Director()
    {
        //this.Movies = new HashSet<Movie>();
    }

    // Primitive properties

    public virtual int DirectorId { get; set; }
    public virtual string Name { get; set; }

    // Navigation properties

    public virtual ICollection<Movie> Movies { get; set; }

}
public partial class Movie
{
    public Movie()
    {
        //this.Actors = new HashSet<Actor>();
    }

    // Primitive properties

    public virtual int MovieId { get; set; }
    public virtual Nullable<int> DirectorId { get; set; }
    public virtual string Name { get; set; }

    // Navigation properties

    public virtual Director Director { get; set; }    
}
公共部分类控制器
{
公共董事()
{
//this.Movies=newhashset();
}
//原始属性
公共虚拟int DirectorId{get;set;}
公共虚拟字符串名称{get;set;}
//导航属性
公共虚拟ICollection电影{get;set;}
}
大众电影
{
公共电影()
{
//this.Actors=new HashSet();
}
//原始属性
公共虚拟int-MovieId{get;set;}
公共虚拟可空目录ID{get;set;}
公共虚拟字符串名称{get;set;}
//导航属性
公共虚拟控制器控制器{get;set;}
}
我有三个问题

  • 我有什么遗漏吗?尽管我对每一个属性都保持“虚拟”,但对象并没有被跟踪。为什么?
  • 我是否必须像在EF4 POCOs中那样编写“关联修正”逻辑
  • 如果是这样,为什么要在DbContext T4 generator中删除关联修复代码
当然,新的导演不会保存,因为您在代码中稍后的某个点将新电影的导演更改为现有的导演,请尝试此导演,然后将其保存到DB中:

var movie = new Movie();
movie.Name = "ABCD";
ctx.Movies.Add(movie);
movie.Director = new Director() { Name = "dir1" };    
//movie.Director = existingDirector;
ctx.SaveChanges();
您可以编写自己的关联修复逻辑,但这将负责保持关联端点的同步,而与此处显示的代码无关

使用EntityObjects时,代码将新控制器保存到DB中的原因是一个称为关系跨度的概念。关系范围定义
ObjectContext将在您将一个实体连接到另一个附着的实体时自动附着该实体。如果分离的对象是新对象,当它附加到上下文时,将添加其EntityState。但是,即使在使用POCO代理(即使导航属性虚拟化)时,也不会实现这种关系范围行为

当然,新导演不会被保存,因为您在代码中稍后的某个点将新电影的导演更改为现有导演,请尝试此导演,您将把它们都保存到DB中:

var movie = new Movie();
movie.Name = "ABCD";
ctx.Movies.Add(movie);
movie.Director = new Director() { Name = "dir1" };    
//movie.Director = existingDirector;
ctx.SaveChanges();
您可以编写自己的关联修复逻辑,但这将负责保持关联端点的同步,而与此处显示的代码无关

使用EntityObjects时,代码将新控制器保存到DB中的原因是一个称为关系跨度的概念。关系范围定义
ObjectContext将在您将一个实体连接到另一个附着的实体时自动附着该实体。如果分离的对象是新对象,当它附加到上下文时,将添加其EntityState。但是,即使在使用POCO代理(即使导航属性虚拟化)时,也不会实现这种关系范围行为

我认为这不是您期望的工作方式的原因是您正在创建电影类本身的实例(即使用新操作符),而不是动态代理。电影类本身没有内置的更改跟踪。因此,在设置Director属性时,不会向DbContext发送通知。即使已将电影添加到DbContext,您仍然在引用原始对象,而不是代理。我认为如果使用DbSet.Create()创建对象(http://msdn.microsoft.com/en-us/library/gg696685(v=vs.103).aspx)它会工作的。

我认为这没有按您期望的方式工作的原因是您正在创建电影类本身的实例(即使用新的操作符),而不是动态代理。电影类本身没有内置的更改跟踪。因此,在设置Director属性时,不会向DbContext发送通知。即使已将电影添加到DbContext,您仍然在引用原始对象,而不是代理。我认为如果使用DbSet.Create()创建对象(http://msdn.microsoft.com/en-us/library/gg696685(v=vs.103).aspx)它可以工作。

代码是哑的,但我想显示EntityObject和DbContext T4生成器之间的差异。关键是使用EntityObject生成器时,相同的代码(不注释行)会在db中创建“dir1”,而POCO或DbContext生成器则不会。为什么?更改跟踪发生了什么?代码是哑的,但我想显示EntityObject和DbContext T4生成器之间的差异。关键是使用EntityObject生成器时,相同的代码(不注释行)会在db中创建“dir1”,而POCO或DbContext生成器则不会。为什么?更改跟踪发生了什么?