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

如何在SQL Server中存储C#的Complex结构体?

问题描述

我在C#类中定义了包含复数类型的实体:

public class DataToStore
{
  [Key]
  public int Id { get; set; }
  public System.Numerics.Complex ComplexValue { get; set; }
}

需要将该数据存储到SQL Server数据库,但SQL中没有直接对应的复数类型。用Entity Framework Core生成数据库架构时,创建迁移报错:

The property 'DataToStore.ComplexValue' could not be mapped because it is of type 'Complex', which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

我清楚报错原因,但不知道SQL中该怎么存这个数据。不局限于用EF Core,手动写SQL实现也可以,目标是能把数据存入并原样取出,请问最佳存储方式是什么?是否需要转换类型?


解决方案

下面是几种可行的存储方案,按需选择:

方案1:拆分实部和虚部分开存储(最推荐)

System.Numerics.Complex本质由两个double类型的**实部(Real)和虚部(Imaginary)**组成,拆分存储是最直观、性能最优的方式:

用EF Core实现

修改实体类,把ComplexValue标记为不映射,拆分出实部和虚部的持久化属性:

public class DataToStore
{
  [Key]
  public int Id { get; set; }
  
  [NotMapped]
  public System.Numerics.Complex ComplexValue 
  { 
    get => new System.Numerics.Complex(RealPart, ImaginaryPart);
    set 
    {
      RealPart = value.Real;
      ImaginaryPart = value.Imaginary;
    }
  }
  
  public double RealPart { get; set; }
  public double ImaginaryPart { get; set; }
}

EF Core会自动将RealPart和ImaginaryPart映射到SQL Server的FLOAT类型(对应C#的double),业务代码中直接使用ComplexValue即可,无需关心底层存储转换。

手动SQL实现

直接在表中创建两个FLOAT类型字段:

CREATE TABLE DataToStore (
  Id INT PRIMARY KEY IDENTITY(1,1),
  RealPart FLOAT NOT NULL,
  ImaginaryPart FLOAT NOT NULL
);

插入数据时拆分实部虚部:

INSERT INTO DataToStore (RealPart, ImaginaryPart) VALUES (3.14, 2.71);

查询后在C#中重新构造Complex对象:

var complex = new System.Numerics.Complex(reader.GetDouble(1), reader.GetDouble(2));

方案2:序列化为二进制存储

如果不想拆分字段,可以把Complex对象序列化为二进制,存储到SQL Server的VARBINARY类型中:

用EF Core实现

添加二进制存储属性,ComplexValue标记为不映射,手动实现序列化逻辑:

public class DataToStore
{
  [Key]
  public int Id { get; set; }
  
  [NotMapped]
  public System.Numerics.Complex ComplexValue 
  { 
    get => DeserializeComplex(ComplexBinary);
    set => ComplexBinary = SerializeComplex(value);
  }
  
  public byte[] ComplexBinary { get; set; }
  
  private byte[] SerializeComplex(System.Numerics.Complex complex)
  {
    using var ms = new MemoryStream();
    using var writer = new BinaryWriter(ms);
    writer.Write(complex.Real);
    writer.Write(complex.Imaginary);
    return ms.ToArray();
  }
  
  private System.Numerics.Complex DeserializeComplex(byte[] data)
  {
    using var ms = new MemoryStream(data);
    using var reader = new BinaryReader(ms);
    var real = reader.ReadDouble();
    var imaginary = reader.ReadDouble();
    return new System.Numerics.Complex(real, imaginary);
  }
}

EF Core会自动将ComplexBinary映射到SQL Server的VARBINARY(MAX)类型。

手动SQL实现

创建表时定义VARBINARY字段:

CREATE TABLE DataToStore (
  Id INT PRIMARY KEY IDENTITY(1,1),
  ComplexBinary VARBINARY(MAX) NOT NULL
);

插入前在C#中完成序列化,查询后反序列化即可还原Complex对象。

方案3:序列化为JSON存储

把Complex序列化为JSON字符串,存储到SQL Server的NVARCHAR或JSON类型中:

用EF Core实现

借助System.Text.Json实现序列化逻辑:

public class DataToStore
{
  [Key]
  public int Id { get; set; }
  
  [NotMapped]
  public System.Numerics.Complex ComplexValue 
  { 
    get => JsonSerializer.Deserialize<System.Numerics.Complex>(ComplexJson);
    set => ComplexJson = JsonSerializer.Serialize(value);
  }
  
  public string ComplexJson { get; set; }
}

如果使用SQL Server 2016及以上版本,还可以通过Fluent API将ComplexJson映射为原生JSON类型:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<DataToStore>()
    .Property(d => d.ComplexJson)
    .HasColumnType("JSON");
}

手动SQL实现

创建表:

CREATE TABLE DataToStore (
  Id INT PRIMARY KEY IDENTITY(1,1),
  ComplexJson NVARCHAR(MAX) NOT NULL
);

插入时存入JSON格式字符串(例如{"Real":3.14,"Imaginary":2.71}),查询后反序列化为Complex对象即可。


方案对比
  • 拆分字段:性能最优,支持SQL层面的数值查询/计算(比如筛选实部大于某个值的记录),推荐优先使用。
  • 二进制存储:存储空间小,序列化/反序列化速度快,但无法在SQL中直接操作复数的数值属性。
  • JSON存储:可读性好,方便手动查看数据,但序列化开销比二进制大;SQL Server 2016+支持JSON查询,但性能仍不如拆分字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:21:05