nav*_*een 26 c# linq generics datatable lambda
免责声明:我知道它在SO的很多地方都被问过.
我的查询有点不同.
编码语言:C#3.5
我有一个名为cardsTable的DataTable从DB中提取数据,我有一个类卡,它只有一些属性(没有构造函数)
public class Cards
{
public Int64 CardID { get; set; }
public string CardName { get; set; }
public Int64 ProjectID { get; set; }
public Double CardWidth { get; set; }
public Double CardHeight { get; set; }
public string Orientation { get; set; }
public string BackgroundImage { get; set; }
public string Background { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想将cardsTable数据插入List类型的对象.
我的数据将在其中包含空字段,因此当我转换数据时该方法不应该出错.以下方法是最好的方法吗?
DataTable dt = GetDataFromDB();
List<Cards> target = dt.AsEnumerable().ToList().ConvertAll(x => new Cards { CardID = (Int64)x.ItemArray[0] });
Run Code Online (Sandbox Code Playgroud)
Jef*_*ado 34
你实际上可以大大缩短它.您可以将Select()扩展方法视为类型转换器.然后可以将转换写为:
List<Cards> target = dt.AsEnumerable()
.Select(row => new Cards
{
// assuming column 0's type is Nullable<long>
CardID = row.Field<long?>(0).GetValueOrDefault(),
CardName = String.IsNullOrEmpty(row.Field<string>(1))
? "not found"
: row.Field<string>(1),
}).ToList();
Run Code Online (Sandbox Code Playgroud)
Tom*_*son 12
我认为如果你使用一些约定和反射,所有的解决方案都可以改进并使方法更通用.比方说,你的名字在数据表名称相同的列在你的对象的属性,那么你可以写一下你的对象的所有属性的东西,然后在数据表映射值查找该列.
我做了相反的事情,那就是......从IList到datatable,我写的代码可以在以下网址看到:http://blog.tomasjansson.com/convert-datatable-to-generic-list-extension/
从另一个角度来看应该不难,并且应该很难重载功能,以便您可以提供要包含或排除哪些属性的信息.
编辑: 所以使其工作的代码是:
public static class DataTableExtensions
{
private static Dictionary<Type,IList<PropertyInfo>> typeDictionary = new Dictionary<Type, IList<PropertyInfo>>();
public static IList<PropertyInfo> GetPropertiesForType<T>()
{
var type = typeof(T);
if(!typeDictionary.ContainsKey(typeof(T)))
{
typeDictionary.Add(type, type.GetProperties().ToList());
}
return typeDictionary[type];
}
public static IList<T> ToList<T>(this DataTable table) where T : new()
{
IList<PropertyInfo> properties = GetPropertiesForType<T>();
IList<T> result = new List<T>();
foreach (var row in table.Rows)
{
var item = CreateItemFromRow<T>((DataRow)row, properties);
result.Add(item);
}
return result;
}
private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
{
T item = new T();
foreach (var property in properties)
{
property.SetValue(item, row[property.Name], null);
}
return item;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你有一个DataTable,你可以写yourTable.ToList<YourType>(),它会为你创建列表.如果您有更复杂的类型与嵌套对象,您需要更新代码.一个建议是重载ToList方法以接受params string[] excludeProperties包含不应映射的所有属性的方法.当然,您可以foreach在CreateItemForRow方法的循环中添加一些空检查.
更新:添加静态字典以存储反射操作的结果,使其更快一点.我没有编译代码,但它应该工作:).
只是一点点简化.我不使用ItemArray:
List<Person> list = tbl.AsEnumerable().Select(x => new Person
{
Id = (Int32) (x["Id"]),
Name = (string) (x["Name"] ?? ""),
LastName = (string) (x["LastName"] ?? "")
}).ToList();
Run Code Online (Sandbox Code Playgroud)
.ToList()位置错误,如果某些字段可以为null,则必须处理这些字段,因为如果它们为null,它们将不会转换为Int64
DataTable dt = GetDataFromDB();
List<Cards> target = dt.AsEnumerable().Select(
x => new Cards { CardID = (Int64)(x.ItemArray[0] ?? 0) }).ToList();
Run Code Online (Sandbox Code Playgroud)