在Entity Framework .NET 8中如何将数据以JSON对象存入SQL Server?
问题解答
一、直接存储目标JSON格式是否可行?
完全可行。SQL Server 2016及以上版本支持通过NVARCHAR(MAX)字段存储JSON数据,还能借助内置的JSON_VALUE、OPENJSON等函数实现JSON内容的查询与操作。
二、两种主要实现方式
方式1:关系型存储(现有实体类默认行为)
你当前的实体类采用嵌套对象设计,在EF Core Code-First模式下,会自动生成关联表结构:
- 主表
InfieldCoachings:包含Id、InfieldCoachingId、CreatedTime、UpdatedTime等字段 - 从属表
Preparations:包含Id、ReviewCustomerDataBeforeVisit、SetSmartObjectivesForVisit、ComplaintHandlingPlan,以及外键InfieldCoachingId关联主表 - 从属表
Openings:结构与Preparations类似,同样通过外键关联主表
这种方式的优势:
- 数据结构清晰,支持SQL精确查询与索引优化
- 符合关系型数据库规范,数据一致性更有保障
方式2:直接存储JSON格式
如果要和你给出的JSON格式完全匹配,可调整实体类,将嵌套对象改为JSON字符串或利用EF Core原生JSON映射:
方案A:手动序列化JSON字符串
namespace Msfa.Api.Entities { public class InfieldCoaching { public int Id { get; set; } public string? InfieldCoachingId { get; set; } // 指定SQL字段类型为nvarchar(max)存储JSON [Column(TypeName = "nvarchar(max)")] public string? Preparation { get; set; } [Column(TypeName = "nvarchar(max)")] public string? Opening { get; set; } public DateTime? CreatedTime { get; set; } public DateTime? UpdatedTime { get; set; } // 补充Swagger请求中的managers字段 public List<string>? Managers { get; set; } } }
写入数据时需手动将Preparation/Opening对象序列化为JSON字符串,读取时反序列化为对象。
方案B:EF Core 7+原生JSON映射(推荐)
无需手动序列化,EF Core会自动处理对象与JSON的转换:
namespace Msfa.Api.Entities { public class InfieldCoaching { public int Id { get; set; } public string? InfieldCoachingId { get; set; } // 标记为JSON类型,SQL Server自动存储为nvarchar(max) [Column(TypeName = "json")] public Preparation? Preparation { get; set; } [Column(TypeName = "json")] public Opening? Opening { get; set; } public DateTime? CreatedTime { get; set; } public DateTime? UpdatedTime { get; set; } public List<string>? Managers { get; set; } } // 保留原有的嵌套类定义 public class Preparation { [Range(1, 5)] public int? ReviewCustomerDataBeforeVisit { get; set; } [Range(1, 5)] public int? SetSmartObjectivesForVisit { get; set; } [Range(1, 5)] public int? ComplaintHandlingPlan { get; set; } } public class Opening { [Range(1, 5)] public int? CreateCustomerAttention { get; set; } [Range(1, 5)] public int? ProductVisibilityChecked { get; set; } [Range(1, 5)] public int? StockLevelsCounted { get; set; } } }
这种方式支持用SQL函数查询JSON内容,例如:
SELECT JSON_VALUE(Preparation, '$.reviewCustomerDataBeforeVisit') FROM InfieldCoachings WHERE Id = 1
三、Code-First模式操作步骤
针对关系型存储
- 在DbContext中添加DbSet:
public class AppDbContext : DbContext { public DbSet<InfieldCoaching> InfieldCoachings { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("你的SQL Server连接字符串"); } }
- 执行迁移命令生成表结构:
Add-Migration InitialCreate Update-Database
针对JSON存储
- 调整实体类(参考方式2的两种方案)
- 配置DbContext中的DbSet
- 执行迁移命令生成包含JSON字段的表
- 写入数据时,EF Core 7+可直接赋值对象;低版本需手动序列化JSON字符串
四、补充说明
- 你的Swagger请求示例包含
managers字段,但现有实体类未定义,需在InfieldCoaching中添加public List<string>? Managers { get; set; }才能接收该参数 - 关系型存储适合结构稳定、需频繁查询单个字段的场景;JSON存储适合结构灵活、无需频繁拆解查询的场景
内容的提问来源于stack exchange,提问作者livealvi
相关产品推荐
相关产品推荐

