如何确定是否可以在不使用异常的情况下将值分配给DataTable列

时间:2014-04-11 13:27:20

标签: c# exception-handling datatable

问题

你好!我想知道是否可以编写这种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
}

我知道这可以在反射的帮助下完成,但我想这样的解决方案甚至比异常方法更慢。

谢谢!

2 个答案:

答案 0 :(得分:1)

我认为我实现了这样的事情。它的核心是基于这样的想法:列可以是有限的类型列表。大多数those types提供TryParse,其他(stringbyte[])更简单。但是因为你不能通过接口调用静态 TryParse方法,并且通过反射调用它有点难看和慢,我决定把它写成生成的模板不同的陈述。这使它保持快速,并允许您编写一个可维护的模板而不是一个可怕的代码文件。

将其保存在.ttT4 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    
}