You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在EF Core中将ScenarioForm以JSON形式存入ScenarioStatus表?

解决方案

针对你的需求——把ScenarioForm以JSON格式作为ScenarioStatus表的一列存储,无需单独建表,以下是两种可行的实现方式:

方案一:使用EF Core内置值转换器(推荐)

.NET 5的EF Core支持通过值转换器直接将复杂类型与数据库中的JSON列映射,无需手动处理序列化逻辑。

步骤:

  1. 修改ScenarioStatus实体,移除Specification属性上的[NotMapped]特性:
using System;
using MyNamespace.Contracts.Forms;
using MyNamespace.Contracts.Models;

namespace MyNamespace.Data.Entities
{
    public class ScenarioStatus
    {
        public Guid Id { get; set; }
        // 移除[NotMapped],让EF Core识别该属性需要映射到数据库列
        public ScenarioForm Specification { get; set; }
        public RunnerType RunnerType { get; set; }
        public DateTime? StartedAt { get; set; }
        public DateTime? CompletedAt { get; set; }
        public TimeSpan? ElapsedTime { get; set; } // 这里建议将ElapsedTime改为TimeSpan类型,更符合耗时的语义
        public string CreatedBy { get; set; }
        public DateTime CreatedAt { get; set; }
        public string UpdatedBy { get; set; }
        public DateTime? UpdatedAt { get; set; }
    }
}
  1. 在你的DbContext的OnModelCreating方法中,用FluentAPI配置值转换器,实现ScenarioForm与JSON字符串的双向转换:
using Microsoft.EntityFrameworkCore;
using MyNamespace.Data.Entities;
using MyNamespace.Contracts.Forms;
using Newtonsoft.Json;

public class YourDbContext : DbContext
{
    public DbSet<ScenarioStatus> ScenarioStatuses { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ScenarioStatus>()
            .Property(s => s.Specification)
            .HasConversion(
                // 序列化:将ScenarioForm对象转为JSON字符串
                form => JsonConvert.SerializeObject(form),
                // 反序列化:将JSON字符串转为ScenarioForm对象
                json => JsonConvert.DeserializeObject<ScenarioForm>(json)
            )
            .HasColumnType("nvarchar(max)"); // 根据数据库类型调整,比如SQL Server用nvarchar(max),PostgreSQL可用jsonb
    }
}

另外,ScenarioForm上的[Keyless]特性可以移除,因为它不是数据库实体,只是一个复杂类型。

方案二:手动处理JSON序列化(自定义程度更高)

如果需要更灵活的序列化控制,可以通过一个字符串属性存储JSON,公开的Specification属性负责转换逻辑。

步骤:

修改ScenarioStatus实体,添加用于存储JSON的字符串属性,同时在Specification的get/set中处理序列化:

using System;
using System.ComponentModel.DataAnnotations.Schema;
using MyNamespace.Contracts.Forms;
using MyNamespace.Contracts.Models;
using Newtonsoft.Json;

namespace MyNamespace.Data.Entities
{
    public class ScenarioStatus
    {
        public Guid Id { get; set; }

        [NotMapped]
        public ScenarioForm Specification
        {
            get => string.IsNullOrEmpty(SpecificationJson) 
                ? new ScenarioForm() 
                : JsonConvert.DeserializeObject<ScenarioForm>(SpecificationJson);
            set => SpecificationJson = JsonConvert.SerializeObject(value);
        }

        // 该属性直接映射到数据库的JSON列,通过[Column]指定列名
        [Column("Specification")]
        public string SpecificationJson { get; set; }

        public RunnerType RunnerType { get; set; }
        public DateTime? StartedAt { get; set; }
        public DateTime? CompletedAt { get; set; }
        public TimeSpan? ElapsedTime { get; set; }
        public string CreatedBy { get; set; }
        public DateTime CreatedAt { get; set; }
        public string UpdatedBy { get; set; }
        public DateTime? UpdatedAt { get; set; }
    }
}

这种方式无需额外配置DbContext,EF Core会自动映射SpecificationJson到数据库的Specification列。

注意事项:

  • 数据库列类型选择:SQL Server可用nvarchar(max)或(2016+版本)JSON类型;PostgreSQL推荐用jsonb,支持索引和查询优化。
  • 若偏好System.Text.Json而非Newtonsoft.Json,只需将序列化代码替换为JsonSerializer.Serialize和JsonSerializer.Deserialize即可。

内容的提问来源于stack exchange,提问作者EtherealRestaurant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:54:22