首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将DataRow值转换为强类型值

将DataRow值转换为强类型值
EN

Stack Overflow用户
提问于 2015-11-10 14:41:41
回答 2查看 6.3K关注 0票数 4

我希望将一个值从一个DataRow转换为一个强类型变量。我想过这样的事情:

代码语言:javascript
复制
int id = row.Field<int>("ID");

但问题是,我们的标准Db返回一个DataTable ,其中每个值都是字符串的类型。意味着每个值都是对象,并且列没有特定的类型。通过这个Field<T>抛出InvalidCastException,因为我试图将对象转换为int。

所以我自己做了件事:

代码语言:javascript
复制
    public static T ConvertTo<T>(this DataRow row, string columnName)
    {
        T returnValue = default(T);

        Type typ = Nullable.GetUnderlyingType(typeof(T));

        if ((row != null) &&
            (row[columnName] != null) &&
            (!Convert.IsDBNull(row[columnName])))
        {
            if (typ == null)
            {
                returnValue = (T)Convert.ChangeType(row[columnName], typeof(T));
            }
            else
            {
                returnValue = (T)Convert.ChangeType(row[columnName], typ);
            }
        }

        return returnValue;
    }

此方法如预期的那样工作。我可以转换可空值、字符串和值类型。好的,我需要抓住例外,如果有人输入像自己的类型的狗屁。但否则就没问题了。

但是,如果我加载一个包含30000行和20列的DataTable,并且希望使用这种方法来转换每个值以进行对象创建,那么我就会发现性能严重不足。如果iam对每个值使用int id = Convert.ToInt32(row["ID"]);等,它比我的一般方法快5-6倍。但是我不喜欢手动地转换它们,特别是当有很多DBNull.Value的时候。

我认为问题在于通过以下方法获得基本类型:

代码语言:javascript
复制
Type typ = Nullable.GetUnderlyingType(typeof(T));

这是自反调用,减慢我的方法。是这样的吗?有没有人有同样的问题,并有一个快速的解决办法?

更新:

我们的标准-选择工作如下:

代码语言:javascript
复制
DbDataAdapter dataAdapter = new DbDataAdapter();
dataAdapter.SelectCommand = cmd;

dataSet = new DataSet();

dataAdapter.Fill(dataSet);
dtReturn = dataSet.Tables[0].Copy();

DbDataAdapter内部使用OracleDataAdapter。

更新:

为了澄清这一点,我正在做以下工作(仅举一个小例子):

我有一个表示select查询的类。例如:

代码语言:javascript
复制
public class Customer
{
  public int Id{get;set}
  public string Name{get;set}
}

在数据库(Oracle)中,我有一个表"Customer“,其中包含2列Id number(5)Name varchar2(100)

现在,我想读取所有客户并将其转换为Customer对象。因此,我通过我们的标准例程SqlSelect读取数据。这将返回一个DataTable。此方法的实习生将在第一次更新下发布。

现在,我循环遍历这个DataRow中的每个DataTable,并将这个单元格值转换为对象创建。

代码语言:javascript
复制
List<Customer> myList = new List<Customer>();
foreach (DataRow row in SqlSelect())
{
  Customer customer = new Customer();
  customer.Id = Convert.ToInt32(row["ID"]);
  customer.Name = Convert.ToString(row["NAME"]);
  myList.Add(customer);
}

这样就没问题了。但我想转化为:

代码语言:javascript
复制
customer.Id = row.ConvertTo<int>("ID");

如果我在“ID”行的DataTable是int,那么Field方法可以很好地处理这个问题。特别是,如果有其他列可以为null等,但在我的示例中,行"ID"是字符串。所以菲尔德不能投这个。我的ConvertTo可以做到这一点,但在大型表上却缺乏很大的性能。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-10 15:14:11

你在这里做的事很奇怪。您必须理解,C#中的所有数据类型都是从对象继承的。所以int,int?,char,double,class MyClass,struct MyStruct,它们都是从对象继承的。

因此,rowcolumnName包含int类型的数据,然后即使它返回对象,也可以直接转换为int。

代码语言:javascript
复制
int i = (int)row[columnName]; //when int data,

这里的例外是,当数据是DBNUll时,必须在转换之前进行测试。实际上不需要转换类,因为它正在大量使用反射,性能损失的根源是什么!

EDIT1:@Scott是对的,我改进了代码,使其对值类型更安全:

代码语言:javascript
复制
public static class IsNullable<T>
{
    private static readonly Type type = typeof(T);
    private static readonly bool is_nullable = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
    public static bool Result { get { return is_nullable; } }
}


 public static class Extension
 {
     public static T CastColumnData<T>(this DataRow row,
                                       string columnName)
    {
        object obj;
        if (row == null) throw new ArgumentNullException("row is null");
        if ((obj = row[columnName]) == null) throw new ArgumentNullException("row[" + columnName + "]  is null");
        bool is_dbnull = obj == DBNull.Value;
        if (is_dbnull && !IsNullable<T>.Result) throw new InvalidCastException("Columns data are DbNull, but the T[" + typeof(T).ToString() + "] is non nullable value type");
        return is_dbnull ? default(T) : (T)obj;
     }
 }

类转换在这里是为了在两种数据类型之间创建等价的值,这些数据类型共享一些共同的东西,但是在这里,使用大量的反射是相当繁重的事情。

对象和int不是等价的,对象由int继承,即使不是直接的.

EDIT2:对原始问题的新更新终于澄清了,所有列类型实际上都是字符串,而不是不同类型的数据类型,必须将它们转换/解析为请求的数据类型。

恐怕没有更快的解决方案了,因为值类型不会从接口与泛型类型实现Parse和TryParse。它们是静态方法,这使得试图通过泛型解决这一问题变得非常困难。

票数 3
EN

Stack Overflow用户

发布于 2015-11-10 15:21:51

这能做你想做的事吗?如果错误频繁发生,就会听到有人在无意中捕捉到它们,但如果不是,我不认为这是一个问题。Convert.ChangeType可能在场景下使用反射,所以这也可能有点慢.

代码语言:javascript
复制
public static T ConvertTo<T>( this DataRow dataRow, string columnName )
{
    var defaultValue = default( T );

    var valueOfCell = GetCellValue(dataRow, columnName);

    if ( defaultValue == null && valueOfCell == null )
    {
        return default( T );
    }

    try
    {
        return ( T )Convert.ChangeType( valueOfCell, typeof( T ) );
    }
    catch ( InvalidCastException ex )
    {
        return default( T );
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33632596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档