C# 实体框架6导航属性加载不工作
被这个奇怪的问题困扰了好几个小时。由于某些原因,entity framework不会加载此1对多关系的导航属性,即使生成的SQL似乎正确,但子项到FrontPageItems之间存在外键: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
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();
}