C# 实体框架6导航属性加载不工作

C# 实体框架6导航属性加载不工作,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,被这个奇怪的问题困扰了好几个小时。由于某些原因,entity framework不会加载此1对多关系的导航属性,即使生成的SQL似乎正确,但子项到FrontPageItems之间存在外键: CONSTRAINT [FK_dbo.SubItems_dbo.FrontPageItems_FrontPageItemId] FOREIGN KEY ([FrontPageItemId]) REFERENCES [dbo].[FrontPageItems] ([Id]) ON D

被这个奇怪的问题困扰了好几个小时。由于某些原因,entity framework不会加载此1对多关系的导航属性,即使生成的SQL似乎正确,但子项到FrontPageItems之间存在外键:

CONSTRAINT [FK_dbo.SubItems_dbo.FrontPageItems_FrontPageItemId] 
    FOREIGN KEY ([FrontPageItemId]) 
        REFERENCES [dbo].[FrontPageItems] ([Id]) ON DELETE CASCADE
我已尝试使用以下内容加载所有frontpageitems:
\u repo.Get()
,但即使
子项
表包含引用
FronPageItems
表的外键,也不会加载导航属性

public class FrontPageItem : Logger, IEntity, IIsPublished
{
    public FrontPageItem()
    {
        SubItems = new HashSet<SubItem>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public bool IsPublished { get; set; }
    public virtual ICollection<SubItem> SubItems { get; set; }
}

    public class SubItem : Logger, IEntity, IIsPublished
{
    public SubItem()
    {
        FrontPageItem = new FrontPageItem();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string YoutubeUrl { get; set; }
    public virtual FrontPageItem FrontPageItem { get; set; }

    public int FrontPageItemId { get; set; }

    public bool IsPublished { get; set; }
}
public class SampleContext : IdentityDbContext<ApplicationUser>
{
    // throwIfV1Schema is used when upgrading Identity in a database from 1 to 2.
    // It's a one time thing and can be safely removed.
    public SampleContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static SampleContext Create()
    {
        return new SampleContext();
    }

    // Define you conceptual model here. Entity Framework will include these types and all their references. 
    public IDbSet<FrontPageItem> FrontPageItem { get; set; }
    public IDbSet<SubItem> SubItems { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // The DateTime type in .NET has the same range and precision as datetime2 in SQL Server.
        // Configure DateTime type to use SQL server datetime2 instead.
        modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

        base.OnModelCreating(modelBuilder);
    }
}

正如DavidG提到的,延迟加载是默认的en-EF。这意味着只有在您实际使用这些属性时,才会加载它们

为了强制包含子项,您可以像这样使用include

FrontPageItem.Include(x => x.SubItems).FirstOrDefault().
modelBuilder.Entity<SubItem>() 
  .HasRequired(t => t.FrontPageItem) 
  .WithMany(t => t.SubItems) 
  .HasForeignKey(d => d.FrontPageItemId) 
  .WillCascadeOnDelete(true);
FrontPageItem这里是您的数据库集。如果您这样查询它,它将加载第一个frontpageitem,其中所有子项都连接到它

更新:如果严格遵守约定,则无需执行此操作,但如果属性的名称不同,或者希望使用显式外键,则可以像这样配置外键

FrontPageItem.Include(x => x.SubItems).FirstOrDefault().
modelBuilder.Entity<SubItem>() 
  .HasRequired(t => t.FrontPageItem) 
  .WithMany(t => t.SubItems) 
  .HasForeignKey(d => d.FrontPageItemId) 
  .WillCascadeOnDelete(true);
modelBuilder.Entity()
.HasRequired(t=>t.FrontPageItem)
.WithMany(t=>t.子项)
.HasForeignKey(d=>d.FrontPageItemId)
.WillCascadeOnDelete(真);

LazyLoadingEnabled
必须为true,而不是false:

context.Configuration.LazyLoadingEnabled=true
; 如果根本没有将LazyLoadingEnabled设置为true,则默认为true

并且
子项
属性必须是虚拟的,才能为此属性启用延迟加载

也可以直接在查询中包含属性。 您还需要使用
modelBuilder

    modelBuilder.Entity<SubItem>() 
  .HasRequired(t => t.FrontPageItem) 
  .WithMany(t => t.SubItems) 
  .HasForeignKey(d => d.FrontPageItemId) 
  .WillCascadeOnDelete(true);

这就是问题所在。由于某种原因,子项中的构造函数是以这种奇怪的行为创建的,其他一切都很好。

什么是
\u repo.Get()
?为什么您希望它自动为您加载相关实体?您是否启用了延迟加载?您在哪里告诉EF它应该如何处理您的关系?我缺少HasRequired(si=>si.FrontPageItem)之类的内容。WithMany(fpi=>fpi.SubItems)。HasForeignKey(si=>si.FrontPageItemId);我使用约定,它似乎生成了正确的SQL:CONSTRAINT[FK_dbo.SubItems_dbo.FrontPageItems_FrontPageItemId]外键([FrontPageItemId])引用[dbo]。[FrontPageItems]([Id]),似乎约定应该处理这个问题:顺便说一句,我尝试了Include技巧。如果我删除公共int-FrontPageItemId{get;set;}属性并让EF为我生成这个foreignkey,它就可以工作了。你说得对,我更新了我的答案。如果希望指定自己的外键,而不是让EF为您生成外键,则可以使用modelbuilder部件。顺便说一句,repo是一个通用的存储库,很抱歉我尝试了所有这些,但都没有成功。我已经在谷歌上读过关于这个问题的帖子,似乎没有什么可以解释为什么我的外键属性让我无法加载导航属性。如果你的特定代码不起作用,也许你可以更新这个问题。另外,如果它是一个通用存储库,您是否可以确切地向您展示您尝试过的include技巧?我已经更新了,并且为了澄清,当我没有在子项中声明foreignkey属性时,这一切都会起作用,这是一个大谜团。它甚至可以在serverexplore中工作,因为我无法在FrontPageItems上选择不存在的子项ID。很抱歉,我的约定与fluent api语句/数据注释的约定非常相似。构造函数有什么问题?我不知道你所说的“问题是什么”…删除这个构造函数使我能够加载导航属性。啊,好的。这很有趣,我希望一些EF专家能够解释为什么这样的构造函数会禁用导航属性加载。我想它可能会覆盖EF的一些默认行为,但我想知道EF实现如何工作的细节。为什么要初始化principle对象?
    public SubItem()
{
    FrontPageItem = new FrontPageItem();
}