web-dev-qa-db-ja.com

DataRowをオブジェクトに変換する方法

プロジェクトでDataRowを作成しました。

DataRow datarow;

このDataRowを任意のタイプのオブジェクトに変換したいと思います。どうすればいいですか?

8
folk

これは私がそれを使用するかなりクールな方法です。

    public static T ToObject<T>(this DataRow dataRow)
    where T : new()
    {
        T item = new T();

        foreach (DataColumn column in dataRow.Table.Columns)
        {
            PropertyInfo property = GetProperty(typeof(T), column.ColumnName);

            if (property != null && dataRow[column] != DBNull.Value && dataRow[column].ToString() != "NULL")
            {
                property.SetValue(item, ChangeType(dataRow[column], property.PropertyType), null);
            }
        }

        return item;
    }

    private static PropertyInfo GetProperty(Type type, string attributeName)
    {
        PropertyInfo property = type.GetProperty(attributeName);

        if (property != null)
        {
            return property;
        }

        return type.GetProperties()
             .Where(p => p.IsDefined(typeof(DisplayAttribute), false) && p.GetCustomAttributes(typeof(DisplayAttribute), false).Cast<DisplayAttribute>().Single().Name == attributeName)
             .FirstOrDefault();
    }

    public static object ChangeType(object value, Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
        {
            if (value == null)
            {
                return null;
            }

            return Convert.ChangeType(value, Nullable.GetUnderlyingType(type));
        }

        return Convert.ChangeType(value, type);
    }
14
class Person{
public string FirstName{get;set;}
public string LastName{get;set;}
}

Person person = new Person();
person.FirstName = dataRow["FirstName"] ;
person.LastName = dataRow["LastName"] ;

または

Person person = new Person();
person.FirstName = dataRow.Field<string>("FirstName");
person.LastName = dataRow.Field<string>("LastName");
6
Avi Fatal

アプリケーションの解決策を1つ見つけました。

    // function that creates an object from the given data row
    public static T CreateItemFromRow<T>(DataRow row) where T : new()
    {
        // create a new object
        T item = new T();

        // set the item
        SetItemFromRow(item, row);

        // return 
        return item;
    }

    public static void SetItemFromRow<T>(T item, DataRow row) where T : new()
    {
        // go through each column
        foreach (DataColumn c in row.Table.Columns)
        {
            // find the property for the column
            PropertyInfo p = item.GetType().GetProperty(c.ColumnName);

            // if exists, set the value
            if (p != null && row[c] != DBNull.Value)
            {
                p.SetValue(item, row[c], null);
            }
        }
    }

これにより、以下のようにDataRowViewModelにマップされます。

Your_ViewModel model = CreateItemFromRow<Your_ViewModel>(row);
5
Bharat

与えられたConverter<TIn, TOut>がデリゲートである場合、以下が機能するはずです。

List<Person> personList = new List<Person>();

personList = ConvertDataRowToList(ds, (row) => {
    return new Person
    {
        FirstName = row["FirstName"],
        LastName  = row["LastName"]
        // Rest of properties should assign here...
    };
});

https://docs.Microsoft.com/en-us/dotnet/api/system.converter-2

2
Thilina H

以前のアプローチのいくつかと同様に、引数オブジェクトを取得するDataRowのこの拡張メソッドを作成しました。主な違いは、オブジェクトのプロパティにデータを入力するだけでなく、特定のオブジェクトのフィールドにもデータを入力することです。これは、より単純な構造でも機能するはずです(ただし、オブジェクトでのみテストしました)。

public static T ToObject<T>( this DataRow dataRow )
     where T : new() {
    T item = new T();
    foreach( DataColumn column in dataRow.Table.Columns ) {
        if( dataRow[column] != DBNull.Value ) {
            PropertyInfo prop = item.GetType().GetProperty( column.ColumnName );
            if( prop != null ) {
                object result = Convert.ChangeType( dataRow[column], prop.PropertyType );
                prop.SetValue( item, result, null );
                continue;
            }
            else {
                FieldInfo fld = item.GetType().GetField( column.ColumnName );
                if( fld != null ) {
                    object result = Convert.ChangeType( dataRow[column], fld.FieldType );
                    fld.SetValue( item, result );
                }
            }
        }
    }
    return item;
}

このコードは、現在のクラスまたはグローバル静的クラスに配置できます。次の名前空間が必要です...

using System;
using System.Data;
using System.Reflection;

使い方は簡単です...

MyClassName obj = dataRow.ToObject<MyClassName>()
1
Nashe

Aviが示す手動の方法とは別に、 AutoMapper のようなマッピングシステムを使用して変換を行うことができます。これは、マップする列/プロパティが多数ある場合に特に役立ちます。

AutoMapperを使用してDataTableをオブジェクトのリストに変換する方法については この記事 を確認してください。

1
Corey

DataRowには、オブジェクト値の配列を含むプロパティItemArrayがあります。この配列を操作して、DataRowの値を使用して任意のカスタム型を作成できます。

0
IDeveloper

これは、DataRowを特定のオブジェクトに変換できる拡張メソッドです。

public static class DataRowExtensions
{
    public static T Cast<T>(this DataRow dataRow) where T : new()
    {
        T item = new T();

        IEnumerable<PropertyInfo> properties = item.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                             .Where(x => x.CanWrite);

        foreach (DataColumn column in dataRow.Table.Columns)
        {
            if (dataRow[column] == DBNull.Value)
            {
                continue;
            }

            PropertyInfo property = properties.FirstOrDefault(x => column.ColumnName.Equals(x.Name, StringComparison.OrdinalIgnoreCase));

            if (property == null)
            {
                continue;
            }

            try
            {
                Type t = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;

                object safeValue = (dataRow[column] == null) ? null : Convert.ChangeType(dataRow[column], t);

                property.SetValue(item, safeValue, null);
            }
            catch
            {
                throw new Exception($"The value '{dataRow[column]}' cannot be mapped to the property '{property.Name}'!");
            }

        }

        return item;
    }
}

そして、あなたはそのように上記の拡張方法を使うことができます

foreach (DataRow row in dataTable.Rows)
{
    SomeClassType obj = row.Cast<SomeClassType>();
    // do something with your object
}
0
Majd Alhayek