【发布时间】:2015-11-20 09:06:18
【问题描述】:
我最近从 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-entity。但是,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 评论)
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() 时,在附加之前不应加载任何引用。但是已经加载了(至少一些)引用。
【问题讨论】:
-
我知道这已经是一项巨大的工作,但您也可以从 dbfirst 更改为 codefirst(通常代码生成器工作正常,因此您只需要检查一切是否仍在工作)。您能否发布一些代码(电影类和检索数据的查询)?
-
不幸的是,更改为 codefirst 不是一种选择。检索数据的查询已显示。在
Locals窗口中查看就足够了,movie.Genre是null。将为Movie添加代码 -
表中存储的实体是否具有正确的 Genre id?
-
@gabriel:是的。外键值存在且正确。当 FK 根本不存在时,数据库将不允许插入。但是是真的。我也检查了这个只是为了确定;)
-
只要确定一下,您可以在明确指定包含中的关系属性的同时使用 Single 检索它吗?
标签: c# sql .net entity-framework entity-framework-6