C# 将DataTable转换为IEnumerable<;T>;
我正在尝试将DataTable转换为IEnumerable。其中T是我创建的自定义类型。我知道我可以通过创建一个C# 将DataTable转换为IEnumerable<;T>;,c#,datatable,ienumerable,C#,Datatable,Ienumerable,我正在尝试将DataTable转换为IEnumerable。其中T是我创建的自定义类型。我知道我可以通过创建一个列表来做到这一点,但我在想,是否有一种更巧妙的方法可以使用IEnumerable来做到这一点。以下是我现在拥有的: private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable) { var tankReadings = new List<TankR
列表
来做到这一点,但我在想,是否有一种更巧妙的方法可以使用IEnumerable来做到这一点。以下是我现在拥有的:
private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
{
var tankReadings = new List<TankReading>();
foreach (DataRow row in dataTable.Rows)
{
var tankReading = new TankReading
{
TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
TankID = Convert.ToInt32(row["TankID"]),
ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
ReadingInches = Convert.ToInt32(row["ReadingInches"]),
MaterialNumber = row["MaterialNumber"].ToString(),
EnteredBy = row["EnteredBy"].ToString(),
ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
MaterialID = Convert.ToInt32(row["MaterialID"]),
Submitted = Convert.ToBoolean(row["Submitted"]),
};
tankReadings.Add(tankReading);
}
return tankReadings.AsEnumerable();
}
private IEnumerable ConvertToTankReaders(数据表)
{
var tankreads=新列表();
foreach(dataTable.Rows中的DataRow行)
{
var tankleading=新的tankleading
{
TankReadingsID=Convert.ToInt32(第[“TRReadingsID”行]),
TankID=Convert.ToInt32(行[“TankID”]),
ReadingDateTime=Convert.ToDateTime(行[“ReadingDateTime”]),
ReadingFoots=Convert.ToInt32(第[“ReadingFoots”]行),
readingiches=Convert.ToInt32(行[“readingiches”),
MaterialNumber=行[“MaterialNumber”]。ToString(),
EnteredBy=行[“EnteredBy”]。ToString(),
ReadingPounds=Convert.ToDecimal(行[“ReadingPounds”]),
MaterialID=转换为32(第[“MaterialID”]行),
已提交=Convert.ToBoolean(行[“已提交”]),
};
油箱读数。添加(油箱读数);
}
返回油箱读数。可计算();
}
关键的部分是我正在创建一个
列表
,然后使用AsEnumerable()
返回它,该实现没有问题。您可以尝试一下yield
关键字,看看您的喜好:
private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
{
foreach (DataRow row in dataTable.Rows)
{
yield return new TankReading
{
TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
TankID = Convert.ToInt32(row["TankID"]),
ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
ReadingInches = Convert.ToInt32(row["ReadingInches"]),
MaterialNumber = row["MaterialNumber"].ToString(),
EnteredBy = row["EnteredBy"].ToString(),
ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
MaterialID = Convert.ToInt32(row["MaterialID"]),
Submitted = Convert.ToBoolean(row["Submitted"]),
};
}
}
private IEnumerable ConvertToTankReaders(数据表)
{
foreach(dataTable.Rows中的DataRow行)
{
产量-返回-新油箱读数
{
TankReadingsID=Convert.ToInt32(第[“TRReadingsID”行]),
TankID=Convert.ToInt32(行[“TankID”]),
ReadingDateTime=Convert.ToDateTime(行[“ReadingDateTime”]),
ReadingFoots=Convert.ToInt32(第[“ReadingFoots”]行),
readingiches=Convert.ToInt32(行[“readingiches”),
MaterialNumber=行[“MaterialNumber”]。ToString(),
EnteredBy=行[“EnteredBy”]。ToString(),
ReadingPounds=Convert.ToDecimal(行[“ReadingPounds”]),
MaterialID=转换为32(第[“MaterialID”]行),
已提交=Convert.ToBoolean(行[“已提交”]),
};
}
}
另外,
AsEnumerable
也不是必需的,因为List
已经是一个IEnumerable
还有一个名为“AsEnumerable()”(在System.Data中)的DataSetExtension方法,它接受一个DataTable并返回一个Enumerable。有关更多详细信息,请参见,但基本上非常简单:
dataTable.AsEnumerable()
缺点是它是枚举DataRow,而不是您的自定义类。“Select()”LINQ调用可以转换行数据,但是:
private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
{
return dataTable.AsEnumerable().Select(row => new TankReading
{
TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
TankID = Convert.ToInt32(row["TankID"]),
ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
ReadingInches = Convert.ToInt32(row["ReadingInches"]),
MaterialNumber = row["MaterialNumber"].ToString(),
EnteredBy = row["EnteredBy"].ToString(),
ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
MaterialID = Convert.ToInt32(row["MaterialID"]),
Submitted = Convert.ToBoolean(row["Submitted"]),
});
}
private IEnumerable ConvertToTankReaders(数据表)
{
返回dataTable.AsEnumerable()。选择(行=>new TankReading
{
TankReadingsID=Convert.ToInt32(第[“TRReadingsID”行]),
TankID=Convert.ToInt32(行[“TankID”]),
ReadingDateTime=Convert.ToDateTime(行[“ReadingDateTime”]),
ReadingFoots=Convert.ToInt32(第[“ReadingFoots”]行),
readingiches=Convert.ToInt32(行[“readingiches”),
MaterialNumber=行[“MaterialNumber”]。ToString(),
EnteredBy=行[“EnteredBy”]。ToString(),
ReadingPounds=Convert.ToDecimal(行[“ReadingPounds”]),
MaterialID=转换为32(第[“MaterialID”]行),
已提交=Convert.ToBoolean(行[“已提交”]),
});
}
使用System.Data.DataSetExtensions的简单方法
:
table.AsEnumerable().Select(row => new TankReading{
TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
TankID = Convert.ToInt32(row["TankID"]),
ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
ReadingInches = Convert.ToInt32(row["ReadingInches"]),
MaterialNumber = row["MaterialNumber"].ToString(),
EnteredBy = row["EnteredBy"].ToString(),
ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
MaterialID = Convert.ToInt32(row["MaterialID"]),
Submitted = Convert.ToBoolean(row["Submitted"]),
});
或:
或者,更好的方法是创建一个tanklreading(DataRow r)
构造函数,然后它变成:
table.AsEnumerable().Select(row => return new TankReading(row));
如果您是从SQL查询生成
DataTable
,您是否考虑过简单地改用Dapper
然后,与使用SqlParameters
和DataTable
和DataAdapter
等创建SqlCommand
命令不同,您只需定义类,使查询列名与字段名匹配,并通过名称轻松绑定参数。您已经定义了TankReading
类,因此它将非常简单
using Dapper;
// Below can be SqlConnection cast to DatabaseConnection, too.
DatabaseConnection connection = // whatever
IEnumerable<TankReading> tankReadings = connection.Query<TankReading>(
"SELECT * from TankReading WHERE Value = @value",
new { value = "tank1" } // note how `value` maps to `@value`
);
return tankReadings;
您可以这样使用:
IEnumerable<TankReading> tankReadings = connection
.Query<DbTankReading>(
"SELECT * from TankReading WHERE Value = @value",
new { value = "tank1" } // note how `value` maps to `@value`
)
.Select(tr => new TankReading(
tr.TankReadingsID,
tr.ReadingDateTime,
tr.ReadingFeet,
tr.ReadingInches,
tr.MaterialNumber,
tr.EnteredBy,
tr.ReadingPounds,
tr.MaterialID,
tr.Submitted
});
IEnumerable tankreads=连接
.查询(
“从TankReading中选择*,其中Value=@Value”,
new{value=“tank1”}//注意'value'如何映射到'@value'`
)
.选择(tr=>新油箱读数(
tr.TankReadingsID,
tr.ReadingDateTime,
读脚,
雷丁奇斯,
tr.材料编号,
文·EnteredBy,
读磅,
物质化,
提交
});
尽管进行了映射工作,但这仍然没有数据表方法那么痛苦。这还允许您执行某种逻辑,尽管如果逻辑不是非常简单的直接映射,我会将逻辑放入一个单独的
TankReadingMapper
类中。DataTable的通用扩展方法。可能有人是相互关联的测试。创建动态属性的想法我来自另一篇文章:
公共统计
using Dapper;
// Below can be SqlConnection cast to DatabaseConnection, too.
DatabaseConnection connection = // whatever
IEnumerable<TankReading> tankReadings = connection.Query<TankReading>(
"SELECT * from TankReading WHERE Value = @value",
new { value = "tank1" } // note how `value` maps to `@value`
);
return tankReadings;
// internal because it should only be used in the data source project and not elsewhere
internal sealed class DbTankReading {
int TankReadingsID { get; set; }
DateTime? ReadingDateTime { get; set; }
int ReadingFeet { get; set; }
int ReadingInches { get; set; }
string MaterialNumber { get; set; }
string EnteredBy { get; set; }
decimal ReadingPounds { get; set; }
int MaterialID { get; set; }
bool Submitted { get; set; }
}
IEnumerable<TankReading> tankReadings = connection
.Query<DbTankReading>(
"SELECT * from TankReading WHERE Value = @value",
new { value = "tank1" } // note how `value` maps to `@value`
)
.Select(tr => new TankReading(
tr.TankReadingsID,
tr.ReadingDateTime,
tr.ReadingFeet,
tr.ReadingInches,
tr.MaterialNumber,
tr.EnteredBy,
tr.ReadingPounds,
tr.MaterialID,
tr.Submitted
});
public static IEnumerable<dynamic> AsEnumerable(this DataTable dt)
{
List<dynamic> result = new List<dynamic>();
Dictionary<string, object> d;
foreach (DataRow dr in dt.Rows)
{
d = new Dictionary<string, object>();
foreach (DataColumn dc in dt.Columns)
d.Add(dc.ColumnName, dr[dc]);
result.Add(GetDynamicObject(d));
}
return result.AsEnumerable<dynamic>();
}
public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
return new MyDynObject(properties);
}
public sealed class MyDynObject : DynamicObject
{
private readonly Dictionary<string, object> _properties;
public MyDynObject(Dictionary<string, object> properties)
{
_properties = properties;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _properties.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_properties.ContainsKey(binder.Name))
{
result = _properties[binder.Name];
return true;
}
else
{
result = null;
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_properties.ContainsKey(binder.Name))
{
_properties[binder.Name] = value;
return true;
}
else
{
return false;
}
}
}
/// <summary>
/// Get entities from DataTable
/// </summary>
/// <typeparam name="T">Type of entity</typeparam>
/// <param name="dt">DataTable</param>
/// <returns></returns>
public IEnumerable<T> GetEntities<T>(DataTable dt)
{
if (dt == null)
{
return null;
}
List<T> returnValue = new List<T>();
List<string> typeProperties = new List<string>();
T typeInstance = Activator.CreateInstance<T>();
foreach (DataColumn column in dt.Columns)
{
var prop = typeInstance.GetType().GetProperty(column.ColumnName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
if (prop != null)
{
typeProperties.Add(column.ColumnName);
}
}
foreach (DataRow row in dt.Rows)
{
T entity = Activator.CreateInstance<T>();
foreach (var propertyName in typeProperties)
{
if (row[propertyName] != DBNull.Value)
{
string str = row[propertyName].GetType().FullName;
if (entity.GetType().GetProperty(propertyName).PropertyType == typeof(System.String))
{
object Val = row[propertyName].ToString();
entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, Val, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
}
else if (entity.GetType().GetProperty(propertyName).PropertyType == typeof(System.Guid))
{
object Val = Guid.Parse(row[propertyName].ToString());
entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, Val, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
}
else
{
entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, row[propertyName], BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
}
}
else
{
entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, null, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
}
}
returnValue.Add(entity);
}
return returnValue.AsEnumerable();
}
static void Main(string[] args)
{
// Convert from a DataTable source to an IEnumerable.
var usersSourceDataTable = CreateMockUserDataTable();
var usersConvertedList = usersSourceDataTable.ToEnumerable<User>();
// Convert from an IEnumerable source to a DataTable.
var usersSourceList = CreateMockUserList();
var usersConvertedDataTable = usersSourceList.ToDataTable<User>();
}