【问题标题】:After upgrading EntityFramework some foreign key reference are not loaded anymore升级 EntityFramework 后,不再加载一些外键引用
【发布时间】:2015-11-20 09:06:18
【问题描述】:

我最近从 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-entity。但是,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 评论)

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&lt;Movie&gt;().Create() 时,在附加之前不应加载任何引用。但是已经加载了(至少一些)引用。

【问题讨论】:

  • 我知道这已经是一项巨大的工作,但您也可以从 dbfirst 更改为 codefirst(通常代码生成器工作正常,因此您只需要检查一切是否仍在工作)。您能否发布一些代码(电影类和检索数据的查询)?
  • 不幸的是,更改为 codefirst 不是一种选择。检索数据的查询已显示。在Locals 窗口中查看就足够了,movie.Genrenull。将为Movie添加代码
  • 表中存储的实体是否具有正确的 Genre id?
  • @gabriel:是的。外键值存在且正确。当 FK 根本不存在时,数据库将不允许插入。但是是真的。我也检查了这个只是为了确定;)
  • 只要确定一下,您可以在明确指定包含中的关系属性的同时使用 Single 检索它吗?

标签: c# sql .net entity-framework entity-framework-6


【解决方案1】:

发现问题: 在这个问题的早期某个地方(这个问题只是一个简化的例子),相关的Genre-entity 已经加载到dbContext,例如用于获取名称“恐怖”的 ID。

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

【讨论】:

    猜你喜欢
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多