如何使用<MODEL>LINQ从DataTable获取IEnumerable的数据?



我有一个DataTable,它有一些属性数据从数据库中获取,DataTable中的每个数据都属于一个产品,每个产品可以有多个特性

所以我有另一个DataTable,它有foreach中的所有产品,通过循环每一行,我将每个产品添加到它的List<Plu>中,如下所示:

var productAttr = new List<Plu.Attributi>();
foreach (DataRow rowPlu in dt.Rows)
{
try
{
int id = (int)rowPlu["ID_PLUREP"];
plu.Add(new Plu(
id,
(string)rowPlu["CODICE_PRP"],
(string)rowPlu[ESTESA],
(string)rowPlu[DESCR], (float)rowPlu["PRE_PRP"],
rowPlu.IsNull("IMG_IMG") ? null : (string)rowPlu["IMG_IMG"],
productAttr,
null,
(int)rowPlu["ID_MENU_PRP"]
));
}
catch
{
return plu;
}
}

目前,productAttr是空的,但现在我需要将其属性添加到每个产品中,因此使用以下函数,我可以获得一个DataTable,其中包含来自数据库的所有产品属性的数据:

var attributi = Attributi(connection, idNegozio);

然后我试图在foreach中做这样的事情

foreach (DataRow rowPlu in dt.Rows)
{
try
{
int id = (int)rowPlu["ID_PLUREP"];
plu.Add(new Plu(
id,
(string)rowPlu["CODICE_PRP"],
(string)rowPlu[ESTESA],
(string)rowPlu[DESCR], (float)rowPlu["PRE_PRP"],
rowPlu.IsNull("IMG_IMG") ? null : (string)rowPlu["IMG_IMG"],
from row in attributi.AsEnumerable() where row.Field<int>("ID_PLUREP_VAT") == id select row,
null,
(int)rowPlu["ID_MENU_PRP"]
));
}
catch
{
return plu;
}
}

但是LINQ返回EnumerableRowCollection,而我需要IEnumerable<Plu.Attribute>,所以我想知道是否有一种懒惰的方法可以将.AsEnumerable转换为IEnumerable<Plu.Attrbute>。。。

问题是,DataTable只知道单元格中有哪些值。它不知道这些价值观代表什么。它不知道0列中的数字实际上是Id。它不知道1列中的字符串是客户的名称,而2列中的DateTime是客户的生日。

如果将来要将此数据表(或类似数据表(的内容用于其他查询,则需要将DataRow转换为它们所代表的项。

一旦您获得了从DataRow到Plu的转换,您就可以将DataTable转换为IEnumerable<Plu>,并对其进行其他LINQ处理。

用法如下:

DataTable table = ...
var mySelectedData = table.AsEnumerable().ToPlus()
.Where(plu => ...)
.Select(plu => new {...})
.ToList();

您需要两个扩展方法:一个将DataRow转换为Plu,另一个将数据行序列转换为Plus序列。参见扩展方法解密

public static Plu ToPlu(this DataRow row)
{
// TODO implement
}
public static IEnumerable<Plu> ToPlus(this IEnumerable<DataRow> dataRows)
{
// TODO: exception if null dataRows
return dataRows.Select(row => row.ToPlu());
}

如果需要,从DataTable创建一个扩展方法来提取Plus:

public static IEnumerable<Plu> ExtractPlus(this DataTable table)
{
// TODO: exception if table null
return table.AsEnumerable().ToPlus();
}

用法:

DataTable table = ...
IEnumerable<Plu> plus = table.ExtractPlus();

我根本不知道Plu是什么,而且你忘了提到Plu的相关属性,所以我给你举一个包含客户的表的例子:

class Customer
{
public int Id {get; set;}              // Id will be in column 0
public string Name {get; set;}         // Name will be in column 1
...
}
public static Customer ToCustomer(this DataRow row)
{
return new Customer
{
Id = (int)row[0],
Name = (string)row[1],
};
}

如果需要,可以使用列的名称来代替columnIndex。

因此,通过只创建一个ToPlu和一个将DataRows序列转换为Plus序列的单行方法,您就可以用您的方法扩展LINQ来读取表。

为了安全起见,可以考虑创建一个扩展方法,将Plus序列转换为DataTable。这样,表的布局就在一个位置:ToPlu(DataRow)ToDataRow(Plu)。表布局的未来变化将更容易管理,DataTable的用户只会按Plus的顺序思考。

您可以执行以下操作。如果您想要IEnumerable<Plu>,您可以从末尾移除.ToList()

dt.AsEnumerable().Select(x => new Plu {
Id = x.Field<int>("ID_PLUREP"),
CodicePrep = x.Field<string>("CODICE_PRP"),
....
Attributes = attributi.AsEnumerable()
.Where(y => y.Field<int>("ID_PLUREP_VAT") == x.Field<int>("ID_PLUREP"))
.Select(z => new Attributi 
{
....
}).ToList(),
....
}).ToList();

最新更新