c# – 实体框架核心两个外键 – 相同表
我遇到了对同一个表有两个外键引用的问题.
填充了外键id字段,但导航字段和列表(团队字段)不是 – 它们都是空的. 我的课程是: public class Team { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Fixture> HomeFixtures { get; set; } public virtual ICollection<Fixture> AwayFixtures { get; set; } } public class Fixture { public int Id { get; set; } public int HomeTeamId { get; set; } public int AwayTeamId { get; set; } public Team HomeTeam { get; set; } public Team AwayTeam { get; set; } } 和我的dbContext public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public DbSet<Team> Teams { get; set; } public DbSet<Fixture> Fixtures { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Fixture>() .HasOne(f => f.HomeTeam) .WithMany(t => t.HomeFixtures) .HasForeignKey(t => t.HomeTeamId) .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict); modelBuilder.Entity<Fixture>() .HasOne(f => f.AwayTeam) .WithMany(t => t.AwayFixtures) .HasForeignKey(t => t.AwayTeamId) .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict); } } 我尝试将[ForeignKey()]属性添加到HomeTeam和AwayTeam属性,但它没有任何效果. modelBuilder.Entity<Team>() .HasMany(t => t.HomeFixtures) .WithOne(f => f.HomeTeam) .HasForeignKey(f => f.HomeTeamId) .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict); 对于远程固定装置也是如此,但这会产生相同的行为. 我的查询方式似乎并不重要,但最简单的情况是 Fixture fixture = await _context.Fixtures.SingleOrDefaultAsync(f => f.Id == id); 返回的fixture对象包含有效且在数据库中但仍未填充Team对象的团队ID. 有谁知道我做错了什么? 解决方法
目前EF Core不支持延迟加载.跟踪问题
here
这意味着默认情况下,导航属性不会被加载并保持为null.作为解决方法,您可以使用预先加载或显式加载模式. 渴望加载 Eager loading是一种模式,您可以在使用Include API运行查询时急切地请求引用的数据.其用法与EF6中的工作方式略有不同.要包含任何导航,请在查询中的include方法中指定lambda表达式(或字符串名称). 例如await _context.Fixtures.Include(f => f.HomeTeam).FirstOrDefaultAsync(f => f.Id == id); 目前,不支持过滤包含,因此您可以请求完全加载导航或排除导航.所以lambda表达式不能复杂.它必须是简单的属性访问.另外,要加载嵌套导航,您可以使用属性访问调用(如a.b.c)链接它们,或者在其收集后导航(因为您无法链接它们)时使用ThenInclude. 例如await _context.Fixtures.Include(f => f.HomeTeam).ThenInclude(t => t.HomeFixtures).FirstOrDefaultAsync(f => f.Id == id); 值得记住的是,include表示从被调用的实体类型导航的路径,以填充路径上的所有naviagations.如果您在第二级或更高级别包含多个导航,通常可能需要编写重复的呼叫.这仅仅是为了语法,查询将被优化,不会重复工作.此外,使用字符串include,您可以指定整个导航路径,而无需使用ThenInclude.由于参考导航可以利用连接来获取单个查询中所需的所有数据,&集合导航可以在单个查询中加载所有相关数据,急切加载是最高效的方式. 明确加载 当您在内存中加载对象并需要加载导航时,延迟加载会在访问导航属性时加载它,如果没有,您需要自己调用Load方法.这些方法在ReferenceEntry或CollectionEntry上定义. 例如 Fixture fixture = await _context.Fixtures.SingleOrDefaultAsync(f => f.Id == id); _context.Entry(fixture).Reference(f => f.HomeTeam).Load(); var team = await _context.Teams.SingleOrDefaultAsync(t => t.Id == id); _context.Entry(team).Collection(f => f.HomeFixtures).Load(); 对于参考导航,您需要在EntityEntry上使用Reference来获取ReferenceEntry.对于集合导航,等效方法是Collection.然后,您只需在其上调用Load方法即可在导航中加载数据.如果需要,还有LoadAsync的异步版本. 希望这可以帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |