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);
}
}