Framework升级到Core以及Dapper支持达梦数据库

.NET Framework 升级到 .NET Core

尝试使用try-convert工具没有成功

手动处理

类库将原有csproj文件内容替换如下

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
    <OutputType>xxx</OutputType>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
  </PropertyGroup>
  <!--保留net452的引用 -->
  <ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
	  <PackageReference Include="Dapper" Version="1.60.6" />
      <!--... -->
  </ItemGroup>

	<!--使用netstandard的引用-->
  <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
	  <PackageReference Include="Dapper" Version="2.0.123" />
      <!--... -->
  </ItemGroup>
</Project>

启动项将原有csproj文件内容替换如下

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
	  <PackageReference Include="DmProvider" Version="1.1.0.11058" />
	  <!--... -->
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\xx\xx.csproj" />
  </ItemGroup>
</Project>

Dapper操作Dm异常问题

Dapper 使用版本 2.0.123
字段在数据库中类型 TINYINT,程序中类型 Int

异常信息

Error parsing column 3 (UField=1 - Byte)  
Unable to cast object of type 'System.Byte' to type 'System.SByte'.

解决方法

SqlMapper.AddTypeHandler方式

参考

SqlMapper.AddTypeHandler(typeof(int), new DMTinyIntTypeHandler());

conn.Query<T>(sql).ToList();

添加 DMTinyIntTypeHandler

internal class DMTinyIntTypeHandler : SqlMapper.ITypeHandler
{
    public void SetValue(IDbDataParameter parameter, object value)
    {
        parameter.Value = value;
    }

    public object Parse(Type destinationType, object value)
    {
        if (value == DBNull.Value || value == null)
            return null;

        switch (value)
        {
            case byte intValue:
                return (int)intValue;
            default:
                return value;
        }
    }
}

手动方式映射

conn.Query<dynamic>(sql).Select(
    p => new T()
    {
        UField = p.UField,
    }).ToList();

查询Dm库时含TinyInt转自定义enum是会报错

System.InvalidCastException: Unable to cast object of type 'System.Byte' to type 'System.SByte'
由于il编写暂时未定位原因,使用手动映射dynamic方式处理了

private static void FlexibleConvertBoxedFromHeadOfStack(ILGenerator il, Type from, Type to, Type via)
{
    MethodInfo op;
    if (from == (via ?? to))
    {
        il.Emit(OpCodes.Unbox_Any, to); // stack is now [target][target][typed-value]
    }
    else if ((op = GetOperator(from, to)) != null)
    {
        // this is handy for things like decimal <===> double
        il.Emit(OpCodes.Unbox_Any, from); // stack is now [target][target][data-typed-value]
        il.Emit(OpCodes.Call, op); // stack is now [target][target][typed-value]
    }
    else
    {
        bool handled = false;
        OpCode opCode = default;
        switch (Type.GetTypeCode(from))
        {
            case TypeCode.Boolean:
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            case TypeCode.UInt32:
            case TypeCode.Int64:
            case TypeCode.UInt64:
            case TypeCode.Single:
            case TypeCode.Double:
                handled = true;
                switch (Type.GetTypeCode(via ?? to))
                {
                    case TypeCode.Byte:
                        opCode = OpCodes.Conv_Ovf_I1_Un; break;
                    case TypeCode.SByte:
                        opCode = OpCodes.Conv_Ovf_I1; break;
                    //...
                }
                break;
        }
    //...
    }
}

Dapper.Contrib添加DmAdapter

Dm.DmException (0x80004005): 第 1 行, 第 62 列[[]附近出现错误
由于项目中使用了Dapper.Contrib的Insert、Update功能较多改起来费时
Dapper.Contrib添加DmAdapter

/// <summary>
/// The Dm database adapter.
/// </summary>
public partial class DmAdapter : ISqlAdapter
{
    /// <summary>
    /// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
    /// </summary>
    /// <param name="connection">The connection to use.</param>
    /// <param name="transaction">The transaction to use.</param>
    /// <param name="commandTimeout">The command timeout to use.</param>
    /// <param name="tableName">The table to insert into.</param>
    /// <param name="columnList">The columns to set with this insert.</param>
    /// <param name="parameterList">The parameters to set for this insert.</param>
    /// <param name="keyProperties">The key columns in this table.</param>
    /// <param name="entityToInsert">The entity to insert.</param>
    /// <returns>The Id of the row created.</returns>
    public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
    {
        var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
        connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
        var r = connection.Query("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout);

        var id = r.First().id;
        if (id == null) return 0;
        var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
        if (propertyInfos.Length == 0) return Convert.ToInt32(id);

        var idp = propertyInfos[0];
        idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);

        return Convert.ToInt32(id);
    }

    /// <summary>
    /// Adds the name of a column.
    /// </summary>
    /// <param name="sb">The string builder  to append to.</param>
    /// <param name="columnName">The column name.</param>
    public void AppendColumnName(StringBuilder sb, string columnName)
    {
        sb.AppendFormat("{0}", columnName);
    }

    /// <summary>
    /// Adds a column equality to a parameter.
    /// </summary>
    /// <param name="sb">The string builder  to append to.</param>
    /// <param name="columnName">The column name.</param>
    public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
    {
        sb.AppendFormat("{0} = :{1}", columnName, columnName);
    }

    /// <summary>
    /// Adds parameter.
    /// </summary>
    /// <param name="sb">The string builder  to append to.</param>
    /// <param name="paramName">The parametr name.</param>
    public void AppendParametr(StringBuilder sb, string paramName)
    {
        sb.AppendFormat(":{0}", paramName);
    }
}
posted @ 2023-03-21 21:04  ddrsql  阅读(273)  评论(1编辑  收藏  举报