1

我正在尝试使用 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 对象中将属性更改为虚拟。下面是代码。

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 生成器中删除了关联修复代码?
4

2 回答 2

1

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

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

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

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

于 2011-02-10T22:23:49.310 回答
0

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

于 2012-04-30T21:23:27.090 回答