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
}
我知道这可以在反射的帮助下完成,但我想这样的解决方案甚至比异常方法更慢。
谢谢!
答案 0 :(得分:1)
我认为我实现了这样的事情。它的核心是基于这样的想法:列可以是有限的类型列表。大多数those types提供TryParse
,其他(string
和byte[]
)更简单。但是因为你不能通过接口调用静态 TryParse
方法,并且通过反射调用它有点难看和慢,我决定把它写成生成的模板不同的陈述。这使它保持快速,并允许您编写一个可维护的模板而不是一个可怕的代码文件。
将其保存在.tt
(T4 template)文件中:
<#@ 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;
}
}
}
}
答案 1 :(得分:0)
我会写一个扩展方法来检查类型是否是有效的数据列类型:
public static bool IsValidType<T>(this DataColumn col, T someStringValue)
{
return col.Datatype == typeof(T);
}
然后做:
if (column.IsValidType(someStringValue)
{
dataRow[dataColumn] = someStringValue
}