C# 升级EntityFramework后,不再加载某些外键引用
我最近将EF4更新为EF6(数据库优先)。 在这里和那里的许多变化之后,一切似乎又像以前一样工作了 不幸的是,现在我面临一个非常奇怪的问题 我有三个简单的表格(C# 升级EntityFramework后,不再加载某些外键引用,c#,sql,.net,entity-framework,entity-framework-6,C#,Sql,.net,Entity Framework,Entity Framework 6,我最近将EF4更新为EF6(数据库优先)。 在这里和那里的许多变化之后,一切似乎又像以前一样工作了 不幸的是,现在我面临一个非常奇怪的问题 我有三个简单的表格(电影,导演,流派)。每个都具有类型为Guid的唯一键(Id) 电影有两个外键。一个给导演,一个给流派 现在,添加一部新电影(导演和类型已经存在) 从EF4开始,启用了延迟加载 检查movie.Director时,我得到了正确的Director-实体。但是,movie.Genre总是null 我已经检查了数据库中的FK约束、生成的edmx、
电影
,导演
,流派
)。每个都具有类型为Guid
的唯一键(Id
)
电影有两个外键。一个给导演
,一个给流派
现在,添加一部新电影(导演和类型已经存在)
从EF4开始,启用了延迟加载
检查movie.Director
时,我得到了正确的Director
-实体。但是,movie.Genre
总是null
我已经检查了数据库中的FK约束、生成的edmx、类以及迄今为止发现的任何内容。我根本不知道是什么导致了这种行为
旁注:这只是一个简化的示例。真正的项目有80多个表,它们之间的关系要多得多。
编辑#1
课程包括电影
、流派
和导演
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; }
}
两个对象都正确加载了属性
编辑#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();
var movie=dbContext.Set().Create();
movie.Name=“霍比特人”;
movie.DirectorId=Guid.Parse(“c3c7606d-35f8-4de4-b7af-89ab19761dc4”);
movie.GenreId=Guid.Parse(“e19e304e-2567-4771-b842-962c067b5565”);
dbContext.Movie.Add(电影);
dbContext.SaveChanges();
相反,movie.Genre
现在已正确设置
我不明白为什么movie.Director
是使用new movie()
设置的,但是movie.Genre
不是。
有人能解释一下吗
根据我的理解(如问题所述),在使用new Movie()
而不是dbContext.Set().Create()
时,在附加之前不应加载引用。但已加载(至少部分)引用。发现问题:
在这个问题的早期上下文中(这个问题只是一个简化的例子),相关的类型
-实体已经加载到dbContext
,例如,用于获取名称“Horror”的Id
总之,这个类型
将映射到新的电影
,因为它已经存在/加载在dbContext中
发现问题:
在这个问题的早期上下文中(这个问题只是一个简化的例子),相关的类型
-实体已经加载到dbContext
,例如,用于获取名称“Horror”的Id
总之,这个
类型
将被映射到新的电影
,因为它已经存在/加载在dbContext
中,我知道这已经是一项巨大的工作,但您也可以从dbfirst更改为codefirst(通常代码生成器工作正常,所以您只需要检查一切是否仍在工作)。您可以发布一些代码(电影类和检索数据的查询)吗?不幸的是,更改为codefirst不是一个选项。已显示检索数据的查询。查看Locals
窗口就足够了,那movie.Genre
是null
。是否为电影添加代码
表中存储的实体是否具有正确的流派id?@gabriel:是。外键值存在且正确。当FK根本不存在时,数据库将不允许插入。但是,这是真的。我也检查了这个,只是为了确定;)只是要确保,在显式指定include中的关系属性的同时,可以使用Single检索它吗?我知道这已经是一项巨大的工作,但您也可以从dbfirst更改为codefirst(通常代码生成器工作正常,因此您只需检查所有内容是否仍在工作)。您可以发布一些代码(电影类和检索数据的查询)吗?不幸的是,更改为codefirst不是一个选项。已显示检索数据的查询。查看Locals
窗口就足够了,那movie.Genre
是null
。是否为电影添加代码
表中存储的实体是否具有正确的流派id?@gabriel:是。外键值存在且正确。当FK根本不存在时,数据库将不允许插入。但是,这是真的。我也检查了这个,只是为了确定;)只是要确保,在显式指定include中的关系属性时,是否可以使用Single检索它?
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);
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();