我在项目中创建了一个DataRow
DataRow datarow;
我想将此数据转换为任何类型的对象。 我怎么能这样做?
答案 0 :(得分:10)
这是我使用它的一种非常酷的方式。
public static T ToObject<T>(this DataRow dataRow)
where T : new()
{
T item = new T();
foreach (DataColumn column in dataRow.Table.Columns)
{
PropertyInfo property = item.GetType().GetProperty(column.ColumnName);
if (property != null && dataRow[column] != DBNull.Value)
{
object result = Convert.ChangeType(dataRow[column], property.PropertyType);
property.SetValue(item, result, null);
}
}
return item;
}
答案 1 :(得分:7)
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");
答案 2 :(得分:5)
我找到了一个解决方案。
// 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);
}
}
}
这会将 DataRow 映射到 ViewModel ,如下所示。
Your_ViewModel model = CreateItemFromRow<Your_ViewModel>(row);
答案 3 :(得分:2)
鉴于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
答案 4 :(得分:1)
除了Avi显示的手动方法之外,您还可以使用AutoMapper等映射系统为您进行转换。这对于要映射大量列/属性的情况特别有用。
查看this article,了解如何使用AutoMapper将DataTable
转换为对象列表。
答案 5 :(得分:1)
类似于某些先前的方法,我为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>()
答案 6 :(得分:0)
DataRow有一个属性ItemArray,它包含一个对象值数组。您可以使用此数组并使用DataRow中的值创建任何自定义类型。
答案 7 :(得分:0)
这里是扩展方法,可让您将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
}
答案 8 :(得分:0)
并发症少;),只需两个步骤即可解决任务: 1.转换为字典(ToDictionary)。 2.将字典映射到实体(MapToEntity)。
public static IDictionary<string, object> ToDictionary(
this DataRow content
)
{
var values = content.ItemArray;
var columns = content
.Table
.Columns
.Cast<DataColumn>()
.Select(x => x.ColumnName);
return values
.Select((v, m) => new { v, m })
.ToDictionary(
x => columns.ElementAt(x.m)
, x => (x.v == DBNull.Value ? null : x.v)
);
}
public static T MapToEntity<T>(
this IDictionary<string, object> source
)
where T : class, new()
{
// t - target
T t_object = new T();
Type t_type = t_object.GetType();
foreach (var kvp in source)
{
PropertyInfo t_property = t_type.GetProperty(kvp.Key);
if (t_property != null)
{
t_property.SetValue(t_object, kvp.Value);
}
}
return t_object;
}
...的用法是:
DataRow dr = getSomeDataRow(someArgs);
ABC result = dr.ToDictionary()
.MapToEntity<ABC>();
答案 9 :(得分:-1)
这些更改对我来说很好,对于字段int,long,int?而且很长?
// 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)
{
if (p.PropertyType.Name == "Int64")
{
p.SetValue(item, long.Parse(row[c].ToString()), null);
}
else if (p.PropertyType.Name == "Int32")
{
p.SetValue(item, int.Parse(row[c].ToString()), null);
}
else if (p.PropertyType.FullName.StartsWith("System.Nullable`1[[System.Int32"))
{
p.SetValue(item, (int?)int.Parse(row[c].ToString()), null);
}
else if (p.PropertyType.FullName.StartsWith("System.Nullable`1[[System.Int64"))
{
p.SetValue(item, (long?)long.Parse(row[c].ToString()), null);
}
else
{
p.SetValue(item, row[c], null);
}
}
}
}