如何确定是否可以在不使用异常的情况下将值分配给DataTable列
本文关键字:情况下 分配 DataTable 异常 是否 何确定 | 更新日期: 2023-09-27 17:57:51
问题
嗨!我想知道是否有可能编写这种C#代码:
try
{
// I know the dataColumn.DataType but the only way I found
// to tell whether the value is actually assignable
// to this column is to assign it and catch the exception
dataRow[dataColumn] = someStringValue;
}
catch (ArgumentException)
{
// Now I know, that the value is not applicable to the type
}
而不使用例外。我的用例是我处理大量的行(1000+),我知道这种情况会经常发生,所以我想避免异常处理的开销以获得性能。那么,有可能像使用字典一样检查这个吗?
bool isAssignable = SomeMagicDataHelper.TrySetValue(dataColumn, someStringValue);
if (!isAssignable)
{
// Now I know, that the value is not applicable to the type
}
我知道这可以在反思的帮助下完成,但我想这样的解决方案会比异常方法更慢。
谢谢!
我想我应该这样实现它。它的核心是基于这样一种思想,即列可以是有限的类型列表。这些类型中的大多数提供TryParse
,而其他类型(string
和byte[]
)则更简单。但是,由于不能通过接口调用staticTryParse
方法,并且通过反射调用它有点难看和缓慢,所以我决定将其作为生成不同语句的模板来编写。这使它保持快速,并允许您编写一个可维护的模板,而不是一个可怕的代码文件。
将其保存在.tt
(T4模板)文件中:
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ output extension=".cs" #>
using System;
using System.Data;
namespace MyApp
{
public static class SomeMagicDataHelper
{
public static bool TrySetValue(DataRow dataRow, DataColumn dataColumn, object value)
{
try
{
if (value == null)
{
if (!dataColumn.AllowDBNull)
return false;
else
{
dataRow[dataColumn] = DBNull.Value;
return true;
}
}
// if the types match exactly, a direct assignment will work
if (value.GetType() == dataColumn.DataType)
{
dataRow[dataColumn] = value;
return true;
}
// otherwise, we'll do a TryParse
switch (dataColumn.DataType.FullName)
{
case "<#= typeof(string).FullName #>":
dataRow[dataColumn] = value;
return true;
case "<#= typeof(byte[]).FullName #>":
return false;
<# foreach (var type in new[] { typeof(Boolean), typeof(Byte), typeof(Char), typeof(DateTime), typeof(Decimal), typeof(Double), typeof(Guid), typeof(Int16), typeof(Int32), typeof(Int64), typeof(SByte), typeof(Single), typeof(TimeSpan), typeof(UInt16), typeof(UInt32), typeof(UInt64) }) {
#> case "<#= type.FullName #>":
{
<#= type.Name #> tryValue;
if (<#= type.Name #>.TryParse(value.ToString(), out tryValue))
{
dataRow[dataColumn] = tryValue;
return true;
}
else
{
return false;
}
}
<# } #>
}
// last resort, might throw an exception
dataRow[dataColumn] = value;
return true;
}
catch (Exception ex)
{
// log ex, this shouldn't be a common thing
return false;
}
}
}
}
我会写一个扩展方法来检查类型是否是有效的数据列类型:
public static bool IsValidType<T>(this DataColumn col, T someStringValue)
{
return col.Datatype == typeof(T);
}
然后执行:
if (column.IsValidType(someStringValue)
{
dataRow[dataColumn] = someStringValue
}