升级EntityFramework后,不再加载某些外键引用
本文关键字:引用 加载 EntityFramework 不再 升级 | 更新日期: 2023-09-27 18:22:44
我最近从EF4更新到EF6(数据库优先)。在经历了许多变化之后,一切似乎又像以前一样运转起来了。
不幸的是,现在我面临着一个非常棘手的问题。
我有三个简单的表(Movie
,Director
,Genre
)。每个具有类型为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
类别Movie
、Genre
和Director
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()
时,在附加之前不应加载任何引用。但是加载了(至少有一些)引用。
发现问题:在这个问题的早期(这个问题只是一个简化的例子),相关的Genre
-实体已经加载到dbContext
中,例如用于获取名称"Horror"的Id。
总之,这个Genre
将被映射到新的Movie
,因为它已经存在/加载在dbContext
中。