我最近从EF4更新到EF6(数据库优先)。 在这里和那里做了很多改变后,一切似乎都像以前一样再次发挥作用。
不幸的是,现在我面临着一个非常普遍的问题。
我有三个简单的表格(Movie
,Director
,Genre
)。每个都有一个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
课程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()
时附加内容之前,不应加载引用。但是(至少有一些)引用被加载了。
答案 0 :(得分:0)
发现问题:
在此问题的上下文中(问题只是一个简化的示例),相关的...
$scope.nameTemplate = $sanitize($templateCache.get('name.html'));
...
- 实体已加载到Genre
,例如获取名称为'Horror'的Id。
然后,此dbContext
将被映射到Genre
已存在/加载的新Movie
。