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

本文关键字:引用 加载 EntityFramework 不再 升级 | 更新日期: 2023-09-27 18:22:44

我最近从EF4更新到EF6(数据库优先)。在经历了许多变化之后,一切似乎又像以前一样运转起来了。

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

我有三个简单的表(MovieDirectorGenre)。每个具有类型为Guid的唯一密钥(Id)。

一部电影有两个外键。一个到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 comment)

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不是。有人能解释一下吗?

根据我的理解(如本问题中所解释的),当使用new Movie()而不是dbContext.Set<Movie>().Create()时,在附加之前不应加载任何引用。但是加载了(至少有一些)引用。

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

发现问题:在这个问题的早期(这个问题只是一个简化的例子),相关的Genre-实体已经加载到dbContext中,例如用于获取名称"Horror"的Id。

总之,这个Genre将被映射到新的Movie,因为它已经存在/加载在dbContext中。