升级EntityFramework后,不再加载某些外键引用

时间:2015-11-20 09:06:18

标签: c# sql .net entity-framework entity-framework-6

我最近从EF4更新到EF6(数据库优先)。 在这里和那里做了很多改变后,一切似乎都像以前一样再次发挥作用。

不幸的是,现在我面临着一个非常普遍的问题。

我有三个简单的表格(MovieDirectorGenre)。每个都有一个Id类型的唯一键(Guid)。

电影有两个外键。一到Director,一到Genre

现在,添加一部新电影(导演和流派已经存在)

var movie = new Movie
{
    Name = "The Hobbit",
    DirectorId = Guid.Parse("c3c7606d-35f8-4de4-b7af-89ab19761dc4"),
    GenreId = Guid.Parse("e19e304e-2567-4771-b842-962c067b5565")
};

dbContext.Movie.Add(movie);
dbContext.SaveChanges();

从EF4开始,延迟加载已启用。

检查movie.Director时,我会获得正确的Director - 实体。但是,movie.Genre始终为null

我已经检查了数据库中的FK约束,生成的edmx,类和我到目前为止发现的任何内容。总之,我无法弄清楚导致这种行为的原因。

旁注:这只是一个简化的例子。真正的项目有80多个表,关系更多。

编辑#1

课程MovieGenreDirector

public partial class Movie
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Movie()
    {
    }

    public System.Guid Id { get; set; }
    public string Name { get; set; }
    public System.Guid DirectorId { get; set; }
    public System.Guid GenreId { get; set; }

    public virtual Director Director { get; set; }
    public virtual Genre Genre { get; set; }
}

public partial class Director
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Director()
    {
        this.Movie = new HashSet<Movie>();
    }

    public System.Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Movie> Movie { get; set; }
}

public partial class Genre
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Genre()
    {
        this.Movie = new HashSet<Movie>();
    }

    public System.Guid Id { get; set; }
    public string Name { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Movie> Movie { get; set; }
}

因此。生成的代码没什么特别的。

编辑#2 (@gabriel评论)

var moviedId = Guid.Parse("de0eca49-eae7-4583-b2e7-0003c148db99");
var theMovie = dbContext.Movie.Single(m => m.Id == moviedId);
var theMovieInclude = dbContext.Movie.Include(m => m.Genre).Single(m => m.Id == moviedId);

两个对象都正确加载了属性。

编辑#3

使用时

var movie = dbContext.Set<Movie>().Create();

movie.Name = "The Hobbit";
movie.DirectorId = Guid.Parse("c3c7606d-35f8-4de4-b7af-89ab19761dc4");
movie.GenreId = Guid.Parse("e19e304e-2567-4771-b842-962c067b5565");

dbContext.Movie.Add(movie);
dbContext.SaveChanges();

现在,movie.Genre已正确设置。

我不明白为什么使用movie.Director设置new Movie(),但movie.Genre不是。 任何人都可以解释一下吗?

根据我的理解(如this问题中所述),在使用new Movie()代替dbContext.Set<Movie>().Create()时附加内容之前,不应加载引用。但是(至少有一些)引用被加载了。

1 个答案:

答案 0 :(得分:0)

发现问题: 在此问题的上下文中(问题只是一个简化的示例),相关的... $scope.nameTemplate = $sanitize($templateCache.get('name.html')); ... - 实体已加载到Genre,例如获取名称为'Horror'的Id。

然后,此dbContext将被映射到Genre已存在/加载的新Movie