在AspNetCore中简单使用EFcore的一对多关系
我们将创建一个简单的示例。
准备两个模型:
- 待办事务列表(TodoList)
一个待办事务列表包含多个事务节点。
- 事务节点 (TransactionNode)
每个事务节点属于一个待办事务列表。
待办事务列表(TodoList)模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace TestEFc_IEQable_AspNetCore01x02 { public class ToDoList { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] [MaxLength(50)] public string? Id { get; set; } public string? ListTitle { get; set; } public string? ListDescription { get; set; } public string? State { get; set; } public List<TransactionNode>? TransactionNodes { get; set; } } }
|
事务节点(TransactionNode)模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema;
namespace TestEFc_IEQable_AspNetCore01x02 { public class TransactionNode { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] [MaxLength(50)] public string? Id { get; set; } public string? SerialNumber { get; set; } public ToDoList? ToDoList { get; set; } public string? State { get; set; } public string? Content { get; set; } } }
|
配置数据库上下文(DbContext):
1 2 3 4 5 6 7 8 9 10 11 12
| using Microsoft.EntityFrameworkCore; namespace TestEFc_IEQable_AspNetCore01x02 { public class DateContext:DbContext { public DateContext(DbContextOptions<DateContext> options) : base(options) { }
public DbSet<ToDoList> ToDoListTable { get; set; } public DbSet<TransactionNode> TransactionNodeTable { get; set; } } }
|
为模型类进行配置:
TodoList和TransactionNode之间的一对多关系可以通过导航属性进行配置。EF Core会自动识别这种关系。
ToDoList:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| using Microsoft.EntityFrameworkCore;
namespace TestEFc_IEQable_AspNetCore01x02 { public class ToDoListConfig: IEntityTypeConfiguration<ToDoList> { public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder<ToDoList> builder) { builder.ToTable("ToDoListTable"); builder.Property(a => a.ListTitle).HasMaxLength(50); builder.Property(a => a.ListDescription).HasMaxLength(250); } } }
|
TransactionNode:
注意这里的HasOne和WithMany的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| using Microsoft.EntityFrameworkCore; namespace TestEFc_IEQable_AspNetCore01x02 { public class TransactionNodeConfig:IEntityTypeConfiguration<TransactionNode> { public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder<TransactionNode> builder) { builder.ToTable("TransactionNodeTable"); builder.HasOne<ToDoList>(a => a.ToDoList).WithMany(c => c.TransactionNodes).IsRequired(); builder.Property(a => a.Content).HasMaxLength(250); } } }
|
program.cs中配置DbContext:
1 2 3
| builder.Services.AddDbContext<DateContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")) );
|
在控制器中使用:
添加数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| [HttpGet] public async Task<ActionResult<string>> Test01_AddData() { var toDolist01 = new ToDoList() { Id = await _idGenService.NewGuidAsync(3), ListTitle = "List02", ListDescription = "List02_Description", State = "0", TransactionNodes = new List<TransactionNode>() }; if (toDolist01.TransactionNodes == null) { return await Task.FromResult("toDolist01.TransactionNodes is null"); } var transactionNode01 = new TransactionNode() { Id = await _idGenService.NewGuidAsync(3), SerialNumber = "01", State = "0", Content = "Content02x01", }; var transactionNode02 = new TransactionNode() { Id = await _idGenService.NewGuidAsync(3), SerialNumber = "02", State = "0", Content = "Content02x02", }; var transactionNode03 = new TransactionNode() { Id = await _idGenService.NewGuidAsync(3), SerialNumber = "03", State = "0", Content = "Content02x03", }; toDolist01.TransactionNodes.Add(transactionNode01); toDolist01.TransactionNodes.Add(transactionNode02); toDolist01.TransactionNodes.Add(transactionNode03); await _dateContext.ToDoListTable.AddAsync(toDolist01); await _dateContext.SaveChangesAsync(); return await Task.FromResult("ok"); }
|
添加数据其实只要注意一下要初始化导航属性的集合就行了,比如上面的TransactionNodes。
查询数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| [HttpGet] public async Task<ActionResult<string>> Test01_GetData() { var toDoList = await _dateContext.ToDoListTable .Include(t => t.TransactionNodes) .FirstOrDefaultAsync(x => x.Id == "84c"); if (toDoList.TransactionNodes == null) { Console.WriteLine("toDoList.TransactionNodes is null"); return await Task.FromResult("toDoList.TransactionNodes is null"); } _logger.LogInformation($"ToDoList Id:{toDoList.Id}, Title:{toDoList.ListTitle}, Description:{toDoList.ListDescription}, State:{toDoList.State}"); foreach (var item in toDoList.TransactionNodes) { _logger.LogInformation($"TransactionNode Id:{item.Id}, SerialNumber:{item.SerialNumber}, Content:{item.Content}, State:{item.State}"); } return await Task.FromResult("ok"); }
|
在查询数据时,注意使用.Include方法来加载导航属性,以确保相关的事务节点也被加载。
查询数据运行截图:
