c# - EFCore 急切加载问题
问题描述
对于为什么这在 EF Core 3.1.8 和 SQLite 中不起作用,我有点困惑。我在具有 int 和 Guid 的两个实体之间有复合外键关系。当我尝试使用商店部分急切加载所有商店时,StoreSection 导航属性未返回任何结果。
我检查了创建的表,数据按预期保存。我检查了生成的优化 sql,当我直接运行它时,结果返回了我期望的结果。下面是一个演示该问题的控制台应用程序。
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
namespace TestEfcore
{
class Program
{
static void Main()
{
Guid userId = Guid.NewGuid();
using (var context = new GroceryManagerContext())
{
var newStore = new Store
{
Name = "Grocery World",
GroceryManagerUserId = userId
};
newStore.StoreSections.Add(new StoreSection() { Name = "Deli", GroceryManagerUserId = userId });
newStore.StoreSections.Add(new StoreSection() { Name = "Produce", GroceryManagerUserId = userId });
context.Add(newStore);
context.SaveChanges();
}
using (var context = new GroceryManagerContext())
{
// Attempting to eager load store sections.
var stores = context.Stores
.Include(s => s.StoreSections)
.Where(s => s.GroceryManagerUserId == userId)
.ToList();
Console.WriteLine($"The user guid is {userId}.");
foreach (var store in stores)
{
Console.WriteLine($"There are {store.StoreSections.Count} store sections in {store.Name}.");
}
}
}
public class Store
{
public int StoreId { get; set; }
public string Name { get; set; } = string.Empty;
public Guid GroceryManagerUserId { get; set; }
public List<StoreSection> StoreSections { get; } = new List<StoreSection>();
}
public class StoreSection
{
public int StoreSectionId { get; set; }
public string Name { get; set; } = string.Empty;
public Guid GroceryManagerUserId { get; set; }
public int StoreId { get; set; }
public Store Store { get; set; } = new Store();
}
public class GroceryManagerContext : DbContext
{
public DbSet<Store>? Stores { get; set; }
public DbSet<StoreSection>? StoreSections { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));
base.OnModelCreating(builder);
builder.Entity<Store>()
.HasIndex(s => new { s.Name, s.GroceryManagerUserId })
.IsUnique();
builder.Entity<StoreSection>()
.HasIndex(ss => new { ss.Name, ss.GroceryManagerUserId })
.IsUnique();
builder.Entity<StoreSection>()
.HasOne(ss => ss.Store)
.WithMany(s => s.StoreSections)
.HasForeignKey(ss => new { ss.StoreId, ss.GroceryManagerUserId })
.HasPrincipalKey(s => new { s.StoreId, s.GroceryManagerUserId })
.IsRequired();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(@"Data Source=D:\src\TestEfcore\TestEfcore\GroceryManager.db");
}
}
}
}
解决方案
StoreSections 导航属性不是预先加载的,因为您正在使用 new 运算符初始化 StoreSection 实体上的 Store 属性。
这导致 StoreSection.StoreId 属性以 0 保存,这会阻止创建关联
您需要更改 StoreSection 实体以删除初始化以解决问题:
public class StoreSection
{
public int StoreSectionId { get; set; }
public string Name { get; set; } = string.Empty;
public Guid GroceryManagerUserId { get; set; }
public int StoreId { get; set; }
public Store Store { get; set; } // initialization has been removed here
}
推荐阅读
- javascript - NVD3如何在折线图中删除Y轴并在删除后还利用Y轴的空间
- angular - Angular 4,单元测试
- rust - 如何指定自定义 Cargo 输出目录?
- spotfire - 在 Spotfire 中应用 Over 函数时如何排除空值
- javascript - 如何使用 AJAX 将代码发送到数据库
- c# - 如何只运行一次浏览器
- mysql - Angular 4 与 nodejs 和 Mysql 连接
- typescript - 函数参数应该是对象的键类型之一
- python - Django 应用启动后仅运行一次命令
- networking - 禁止用户文件夹通过网络共享 Windows 10