Reb*_*a J 2 c# entity-framework-core .net-core
我有 3 个实体:
public partial class Category
{
public int CategoryID { get; set; }
public string? CategoryName { get; set; }
public ICollection<BookCategory> BookCategory { get; set; }
}
public partial class BookCategory
{
public int CategoryID { get; set; }
public int BookID { get; set; }
public Category Category { get; set; }
public Book Book { get; set; }
}
public partial class Book
{
public int BookID { get; set; }
public string? Title { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我希望返回一个 Category 数组,以及一个 BookCategory 子数组,它与 Book 一对一。
使用这样的调用;
public async Task<List<Category>> test()
{
var query = dbContext.Category
.Include(p => p.BookCategory)
.ThenInclude(pc => pc.Book)
.OrderBy(p => p.CategoryID) as IQueryable<Category>;
var data = await query.ToListAsync();
return data;
}
Run Code Online (Sandbox Code Playgroud)
我有这样的虚拟数据:
insert into kiosk.Category (CategoryID, CategoryName) values (1, 'Horror')
insert into kiosk.Category (CategoryID, CategoryName) values (2, 'Fantasy')
insert into kiosk.Book (BookID, Title) values (1, 'Space shooty')
insert into kiosk.Book (BookID, Title) values (2, 'Elf shooty')
insert into kiosk.BookCategory (BookID, CategoryID) values (1, 2)
insert into kiosk.BookCategory (BookID, CategoryID) values (2, 2)
Run Code Online (Sandbox Code Playgroud)
但是,我收到的此请求的响应只给了我一个类别 2 的记录,而不是预期的两个。
[
{
"categoryID": 1,
"categoryName": "Horror",
"bookCategory": []
},
{
"categoryID": 2,
"categoryName": "Fantasy",
"bookCategory": [
{
"categoryID": 2,
"bookID": 1,
"book": {
"bookID": 1,
"title": "Space shooty"
}
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
数据库上下文:
public class BooksDbContext : DbContext
{
public DbSet<Book> book { get; set; }
public DbSet<Category> Category { get; set; }
public DbSet<BookCategory> BookCategory { get; set; }
public BooksDbContext()
{ }
public BooksDbContext(DbContextOptions options) : base(options)
{ }
public BooksDbContext(string connectionString)
{
this.connectionString = connectionString;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema("dbo");
modelBuilder.ApplyConfiguration(new BookCategoryConfiguration());
modelBuilder.ApplyConfiguration(new CategoryTestConfiguration());
modelBuilder.ApplyConfiguration(new BookConfiguration());
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
if (!string.IsNullOrWhiteSpace(connectionString))
{
optionsBuilder.UseSqlServer(connectionString);
}
}
}
Run Code Online (Sandbox Code Playgroud)
三种配置如下
public class BookCategoryConfiguration : IEntityTypeConfiguration<BookCategory>
{
public void Configure(EntityTypeBuilder<BookCategory> builder)
{
builder.ToTable("BookCategory");
builder.HasKey(x => x.BookID);
builder.HasKey(x => x.CategoryID);
builder.HasOne(a => a.Category).WithMany(b => b.BookCategory).HasForeignKey(c => c.CategoryID); // FK_POSCategoryProduct_POSCategory
}
}
public class CategoryTestConfiguration : IEntityTypeConfiguration<Category>
{
public void Configure(EntityTypeBuilder<Category> builder)
{
builder.ToTable("Category");
builder.HasKey(x => x.CategoryID);
builder.Property(x => x.CategoryID).HasColumnName(@"CategoryID").HasColumnType("int").IsRequired();
builder.Property(x => x.CategoryName).HasColumnName(@"CategoryName").HasColumnType("nvarchar").HasMaxLength(50);
}
}
public class BookConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("Book");
builder.HasKey(x => x.BookID);
builder.Property(x => x.BookID).HasColumnName(@"BookID").HasColumnType("int").IsRequired();
builder.Property(x => x.Title).HasColumnName(@"Title").HasColumnType("nvarchar").HasMaxLength(50);
}
}
Run Code Online (Sandbox Code Playgroud)
该模型通过显式连接实体表示标准的多对多关系。
问题是join实体键的流畅映射:
builder.HasKey(x => x.BookID);
builder.HasKey(x => x.CategoryID);
Run Code Online (Sandbox Code Playgroud)
该HasKey方法(与大多数流畅的 API 一样)不是可加的。后一个调用获胜(取代前一个调用)。
上面代码的效果是 EF Core 认为是表CategoryID的唯一键BookCategory,因此每个 仅加载 1 条记录CategoryID。
当然,这个想法是定义连接实体的标准复合主键。这是通过使用匿名类型(在 EF Core Keys文档主题的复合键部分示例中显示)来实现的(类似于所有允许多个属性的 fluent API )。
将它应用于您的场景将替换上面的 2 行
builder.HasKey(x => new { x.BookID, x.CategoryID });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
946 次 |
| 最近记录: |