C#中LINQ?to?DataSet操作及DataTable與LINQ相互轉(zhuǎn)換
一、DataTable的擴(kuò)展方法:
1、DataTable轉(zhuǎn)Linq:AsEnumerable 方法
返回的EnumerableRowCollection<DataRow> 實(shí)現(xiàn)了 IEnumerable<T>接口。其中泛型參數(shù)T是DataRow。
此對(duì)象可用在 LINQ表達(dá)式或方法查詢中。
語法:
public static EnumerableRowCollection<DataRow> AsEnumerable (this DataTable source);
在以下示例中,一個(gè) DataColumn 數(shù)據(jù)表ProductName,提取ProductName值,然后將值輸出。
DataTable table = new DataTable();
table.Columns.Add("ID");
table.Columns.Add("ProductName");
table.Rows.Add("1", "Chai");
table.Rows.Add("2", "Queso Cabrales");
table.Rows.Add("3", "Tofu");
var productNames = from products in table.AsEnumerable()
select products.Field<string>("ProductName");
Console.WriteLine("Product Names: ");
foreach (string productName in productNames)
{
Console.WriteLine(productName);
}注意:轉(zhuǎn)成EnumerableRowCollection后,需要對(duì)兩個(gè)這樣的行集合進(jìn)行操作,如:Distinct,Union,Except,Intesect,SequenceEqual都需要對(duì)數(shù)據(jù)源的元素進(jìn)行相等比較,需要使用專門為Linq To Datatable新增加的DataRowComparer作為參數(shù)(實(shí)現(xiàn)了IEqulityComparer接口),用于比較DataRow的值(而不是引用比較)。否則,根本不能達(dá)到預(yù)期操作。
IEnumerable<DataRow> distinctTable = table.AsEnumerable().Distinct(DataRowComparer.Default);
2、Linq轉(zhuǎn)DataTable
(1)返回DataTable,其中包含的副本DataRow對(duì)象。
public static DataTable CopyToDataTable<T> (this IEnumerable<T> source) where T : DataRow;
以下示例查詢 SalesOrderHeader 表的訂單后 2001 年 8 月 8 日,并使用CopyToDataTable方法來創(chuàng)建DataTable從該查詢。
DataTable orders = ds.Tables["SalesOrderHeader"];
IEnumerable<DataRow> query =
from order in orders.AsEnumerable()
where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
select order;
// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();(2)副本表的DataRow到指定的對(duì)象DataTable。
public static void CopyToDataTable<T> (this IEnumerable<T> source, DataTable table, LoadOption options) where T : DataRow;
LoadOption:當(dāng)使用 Load 或 Load 方法時(shí)控制數(shù)據(jù)源中的值如何應(yīng)用至現(xiàn)有行。
- OverwriteChanges:傳入此行的值將同時(shí)寫入每列數(shù)據(jù)的當(dāng)前值和原始值版本。
- PreserveChanges:傳入此行的值將寫入每列數(shù)據(jù)的原始值版本。 每列數(shù)據(jù)的當(dāng)前版本不變化。 這是默認(rèn)設(shè)置。
- Upsert:傳入此行的值將寫入每列數(shù)據(jù)的當(dāng)前版本。 每列數(shù)據(jù)的原始版本不變化。
以下示例:如果tableold表設(shè)置了主鍵,則可以合并記錄,否則追加。
table.AsEnumerable().CopyToDataTable(tableold,LoadOption.OverwriteChanges);
tips:默認(rèn)情況下(沒對(duì)表進(jìn)行操作),數(shù)據(jù)行的Original版本是不存在的,視圖訪問將報(bào)錯(cuò)??梢栽谠L問之前使用DataRow.HasVersion來判斷,也可以通過調(diào)用DataRow.AcceptChanges()方法來建立Original版本,避免異常發(fā)生。
二、DataRow中的擴(kuò)展方法:
(1)獲取字段值
Field:提供對(duì) DataRow 中的每個(gè)列值的強(qiáng)類型訪問。
public static T Field<T> (this DataRow row, string columnName);
舉例:
foreach (DataRow row in table.AsEnumerable())
{
row.Field<int>("Id");
row.Field<string>("Name", DataRowVersion.Original);
}(2)設(shè)置字段值
Set?Field:為 DataRow 中的指定列設(shè)置一個(gè)新值。
public static void SetField<T> (DataRow row, string columnName, T value);
如果value是null,則SetField方法轉(zhuǎn)換null值設(shè)置為DBNull.Value。
舉例:
var rows = from s in table.AsEnumerable()
where s.Field<string>("Name") == "c"
select s;
rows.Single<DataRow>().SetField("Name", "cc");三、Linq To DataTable的常見用法。
1、查詢:
DataTable table = new DataTable();
table.Columns.Add("ID", Type.GetType("System.Int32"));
table.Columns.Add("PID", Type.GetType("System.Int32"));
table.Columns.Add("CreateDate", Type.GetType("System.DateTime"));
table.Rows.Add(1, 2, "2010-1-1");
table.Rows.Add(2, 3, "2011-1-1");
table.Rows.Add(3, 3, "2012-1-1");
table.Rows.Add(4, 2, null);
var rows = from s in table.AsEnumerable()
where s.Field<int>("ID") > 1 && !s.IsNull("CreateDate")
select new
{
ID = s["ID"],
CreateDate = s["CreateDate"]
};
rows.ToList().ForEach(m => Console.WriteLine(m.ID + "-" + m.CreateDate));//2-2011-01-01 0:00:00 3-2012-01-01 0:00:002、分組:
var query = from r in table.AsEnumerable()
group r by new
{
PID = r.Field<int>("PID")
} into g
select new
{
Pid = g.Key.PID,
FirstCreateDate = g.First().Field<DateTime>("CreateDate"),
IDS = string.Join(",", g.Select(n => n.Field<int>("ID")).ToArray()),
Count = g.Count(q => q.Field<int>("ID") > 1),
Sum1 = g.Sum(q => q.Field<int>("ID"))
};
query.ToList().ForEach(m => Console.WriteLine(m.Pid + "-" + m.FirstCreateDate + "-" + m.IDS));//2-2010-01-01 0:00:00-1,4 3-2011-01-01 0:00:00-2,3例2:按PID分組,獲取倒數(shù)第二條信息
var query1 = from r in table.AsEnumerable()
where new int[] { 3, 4 }.Contains(r.Field<int>("PID"))
orderby r.Field<DateTime>("CreateDate") descending
group r by r.Field<int>("PID") into g
let n = (from d in g.Take(2).Skip(1) select d).FirstOrDefault()
select new
{
PID = g.Key,
ID = n.Field<int>("ID"),
CreateDate = n.Field<DateTime>("CreateDate")
};
query1.ToList().ForEach(m => Console.WriteLine(m.PID + "-" + m.ID + "-" + m.CreateDate));//3-2-2011-01-01 0:00:003、Join組合查詢:
var result = from t1 in table.AsEnumerable()
join t2 in table.AsEnumerable() on
t1.Field<int>("ID") equals t2.Field<int>("ID")
where t2.Field<DateTime?>("CreateDate") < DateTime.Today || !t2.Field<DateTime?>("CreateDate").HasValue
select new
{
ID = t2.Field<int>("ID"),
CreateDate = t1.Field<DateTime?>("CreateDate")
};
result.ToList().ForEach(m => Console.WriteLine(m.ID + "-" + m.CreateDate));到此這篇關(guān)于C#中LINQ to DataSet操作及DataTable與LINQ相互轉(zhuǎn)換的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Unity實(shí)現(xiàn)多平臺(tái)二維碼掃描
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)多平臺(tái)二維碼掃描,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
C#中IList<T>與List<T>的區(qū)別深入解析
本篇文章主要是對(duì)C#中IList<T>與List<T>的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-01-01

