Skip to content

类型处理器

SmartSql 的类型处理器系统弥合了 .NET 类型和数据库列类型之间的差距。虽然核心库为标准基本类型提供了处理器,但 SmartSql.TypeHandlerSmartSql.TypeHandler.PostgreSql 包为复杂的序列化需求添加了处理器:存储在文本列中的 JSON 对象、加密字符串、XML 序列化值,以及 PostgreSQL 特定类型如数组、几何形状和网络地址。

一览表

包名用途关键处理器
SmartSql.TypeHandlerJSON、XML、加密序列化JsonTypeHandlerXmlTypeHandlerCryptoTypeHandler
SmartSql.TypeHandler.PostgreSqlPostgreSQL 原生类型JsonTypeHandlerPointTypeHandler、数组处理器等

类型处理器层次结构

mermaid
classDiagram
    class ITypeHandler {
        <<interface>>
        +GetValue(dataReader, columnIndex, targetType) object
        +GetSetParameterValue(value) object
        +Initialize(parameters)
    }

    class AbstractNullableTypeHandler~TProperty,TField~ {
        <<abstract>>
        +GetValue() object
        #GetValueWhenNotNull()* TProperty
        #GetSetParameterValueWhenNotNull()* object
    }

    class JsonTypeHandler {
        +GetValue() object
        #GetSetParameterValueWhenNotNull() object
    }

    class JsonTypeHandler~T~ {
        #JsonSerializerSettings
        +Initialize(parameters)
        +GetValue() TProperty
        #GetSetParameterValueWhenNotNull() object
    }

    class XmlTypeHandler {
        +GetValue() object
        #GetSetParameterValueWhenNotNull() object
    }

    class CryptoTypeHandler {
        -ICrypto _crypto
        +Initialize(parameters)
        #GetValueWhenNotNull() string
        #GetSetParameterValueWhenNotNull() object
    }

    class PgJsonTypeHandler {
        +GetValue() object
        #GetSetParameterValueWhenNotNull() object
    }

    class PgPointTypeHandler {
        +GetValue() object
        #GetSetParameterValueWhenNotNull() object
    }

    class PgInt32ArrayTypeHandler {
        +GetValue() object
        #GetSetParameterValueWhenNotNull() object
    }

    ITypeHandler <|.. AbstractNullableTypeHandler
    AbstractNullableTypeHandler <|-- JsonTypeHandler~T~
    JsonTypeHandler <|-- JsonTypeHandler
    AbstractNullableTypeHandler <|-- XmlTypeHandler
    AbstractNullableTypeHandler <|-- CryptoTypeHandler
    AbstractNullableTypeHandler <|-- PgJsonTypeHandler
    AbstractNullableTypeHandler <|-- PgPointTypeHandler
    AbstractNullableTypeHandler <|-- PgInt32ArrayTypeHandler

    style ITypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style AbstractNullableTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style JsonTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style JsonTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style XmlTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CryptoTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style PgJsonTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style PgPointTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style PgInt32ArrayTypeHandler fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

JSON 类型处理器

JsonTypeHandler<TProperty> 将复杂的 .NET 对象序列化/反序列化为存储在数据库文本列中的 JSON 字符串。它支持可配置的命名策略和日期格式。

工作原理

mermaid
sequenceDiagram
autonumber
    participant Reader as DataReader
    participant Handler as JsonTypeHandler~T~
    participant JSON as JsonConvert

    Note over Reader: Reading from DB
    Reader->>Handler: GetValue(dataReader, columnIndex, targetType)
    Handler->>Reader: GetString(columnIndex)
    Reader-->>Handler: jsonStr
    Handler->>JSON: Deserialize(jsonStr, targetType, settings)
    JSON-->>Handler: TProperty object
    Handler-->>Reader: Return object

    Note over Handler: Writing to DB
    Handler->>JSON: SerializeObject(parameterValue, settings)
    JSON-->>Handler: jsonStr
    Handler-->>Handler: Return jsonStr as parameter value

配置属性

属性描述
DateFormat例如 "yyyy-MM-dd"自定义序列化日期格式
NamingStrategy"Camel""Snake"、默认值JSON 中的属性命名约定

XML 配置

xml
<TypeHandlers>
  <TypeHandler Name="Json"
    Type="SmartSql.TypeHandler.JsonTypeHandler`1, SmartSql.TypeHandler">
    <Properties>
      <Property Key="NamingStrategy" Value="Camel"/>
      <Property Key="DateFormat" Value="yyyy-MM-dd"/>
    </Properties>
  </TypeHandler>
</TypeHandlers>

非泛型用法

非泛型的 JsonTypeHandler 继承自 JsonTypeHandler<Object>,可作为任何类型的即插即用替代:

xml
<TypeHandler Name="Json"
  Type="SmartSql.TypeHandler.JsonTypeHandler, SmartSql.TypeHandler"/>

XML 类型处理器

XmlTypeHandler 将对象序列化为 XML 字符串,使用 System.Xml.Serialization 反序列化:

csharp
// Reading: xmlStr -> XmlDeserialize -> object
// Writing: object -> XmlSerialize -> xmlStr

加密类型处理器

CryptoTypeHandler 使用可插拔的 ICrypto 实现在写入时透明加密数据、读取时透明解密:

mermaid
flowchart LR
    subgraph CryptoFlow["CryptoTypeHandler Flow"]
        style CryptoFlow fill:#161b22,stroke:#30363d,color:#e6edf3
        W["Write: plaintext"] --> Enc["ICrypto.Encrypt()"]
        Enc --> DB1["DB: encrypted string"]
        DB2["DB: encrypted string"] --> Dec["ICrypto.Decrypt()"]
        Dec --> R["Read: plaintext"]
    end

    style W fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Enc fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DB1 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DB2 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Dec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style R fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

加密实现通过 Initialize(parameters) 方法选择。在 XML 中配置时,提供 CryptoFactory.Create() 能识别的属性。

PostgreSQL 类型处理器

SmartSql.TypeHandler.PostgreSql 包为 PostgreSQL 特定类型提供了处理器:

处理器.NET 类型PostgreSQL 类型
JsonTypeHandlerobjectjson / jsonb
JsonTypeHandler<T>Tjson / jsonb
PointTypeHandlerNpgsqlPointpoint
LineTypeHandlerNpgsqlLineline
LineSegmentTypeHandlerNpgsqlLSeglseg
BoxTypeHandlerNpgsqlBoxbox
PathTypeHandlerNpgsqlPathpath
PolygonTypeHandlerNpgsqlPolygonpolygon
CircleTypeHandlerNpgsqlCirclecircle
InetTypeHandlerNpgsqlInetinet
StringArrayTypeHandlerstring[]text[]
Int16ArrayTypeHandlershort[]smallint[]
Int32ArrayTypeHandlerint[]integer[]
Int64ArrayTypeHandlerlong[]bigint[]
DecimalArrayTypeHandlerdecimal[]numeric[]
GuidArrayTypeHandlerGuid[]uuid[]
DictionaryTypeHandlerDictionaryhstore

数组处理器用法

xml
<TypeHandler Name="IntArray"
  Type="SmartSql.TypeHandler.PostgreSql.Int32ArrayTypeHandler, SmartSql.TypeHandler.PostgreSql"/>

注册自定义类型处理器

在 XML 配置中

xml
<SmartSqlMap Scope="MyScope">
  <TypeHandlers>
    <TypeHandler Name="MyJson"
      Type="SmartSql.TypeHandler.JsonTypeHandler`1, SmartSql.TypeHandler">
      <Properties>
        <Property Key="NamingStrategy" Value="Camel"/>
      </Properties>
    </TypeHandler>
  </TypeHandlers>
</SmartSqlMap>

在 Options 模式中(appsettings.json)

json
{
  "TypeHandlers": [
    {
      "Name": "Json",
      "Type": "SmartSql.TypeHandler.JsonTypeHandler`1, SmartSql.TypeHandler",
      "Properties": {
        "NamingStrategy": "Camel"
      }
    }
  ]
}

在 SmartSqlBuilder 中

csharp
builder.AddTypeHandler(typeof(MyEntity), new JsonTypeHandler<MyEntity>());

通过仓储上的 [Param] 属性

csharp
[Statement(Sql = "INSERT INTO Orders (Data) VALUES (?data)")]
int InsertOrder([Param("data", TypeHandler = "Json")] OrderData data);

类型处理器与批量插入的集成

当使用 BulkExtensions.ToDataTable<T>() 时,实体元数据缓存使用注册的类型处理器将属性值转换为 DataTable 中的数据库兼容值:

csharp
// In BulkExtensions.ToDataTable:
if (columnIndex.Value.Handler != null)
{
    dataRow[columnIndex.Key] = columnIndex.Value.Handler.GetSetParameterValue(propertyVal);
}

交叉参考

  • Options 模式 -- 在 appsettings.json 中注册类型处理器。
  • 批量插入 -- 类型处理器影响批量数据转换。
  • 动态仓储 -- 使用 [Param(TypeHandler = "...")] 为每个参数指定处理器。

参考资料

基于 MIT 许可证发布。