【问题标题】:EntityFramework CTP5 change trackingEntityFramework CTP5 变更跟踪
【发布时间】:2011-02-10 21:48:13
【问题描述】:

我正在尝试使用 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”。如果我使用 CTP 5 DbContext 生成器运行此代码,则不会创建新的导演“dir1”。我在 Movie 和 Director 对象中将属性更改为 virtual。下面是代码。

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; }    
}

我有 3 个问题。

  • 我在这里遗漏了什么吗?即使我为每个属性都保留了“虚拟”,但对象并没有被跟踪。为什么?
  • 我是否必须像在 EF4 POCO 中那样编写“关联修复”逻辑?
  • 如果是这样,为什么在 DbContext T4 生成器中删除了关联修复代码?

【问题讨论】:

    标签: entity-framework poco entity-framework-ctp5


    【解决方案1】:

    当然,新导演不会被保存,因为您稍后在代码中将新电影的导演更改为现有导演,试试这个,您会将它们都保存到数据库中:

    var movie = new Movie();
    movie.Name = "ABCD";
    ctx.Movies.Add(movie);
    movie.Director = new Director() { Name = "dir1" };    
    //movie.Director = existingDirector;
    ctx.SaveChanges();
    

    您可以编写自己的关联修复逻辑,但这将负责保持关联的端点同步,并且与您在此处显示的代码无关。

    您的代码在使用 EntityObjects 时将新导向器保存到数据库中的原因是因为一个名为 Relationship Span 的概念。关系跨度定义了 当您将实体连接到另一个附加实体时,ObjectContext 将自动附加该实体。如果该分离的对象是新的,当它附加到上下文时,它的 EntityState 将被添加。但是,即使您使用 POCO 代理(即使您的导航属性虚拟化),也不会实现此关系跨度行为。

    【讨论】:

    • 代码很笨,但我想展示 EntityObject 和 DbContext T4 生成器之间的差异。关键是使用 EntityObject 生成器,相同的代码(不注释行)在 db 中创建“dir1”,而 POCO 或 DbContext 生成器没有。为什么?更改跟踪发生了什么?
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多