• C#(99):LINQ to DataSet,对离线数据的Linq支持、AsEnumeable()


    一、DataTable的扩展方法:

    1、DataTable转Linq:AsEnumerable 方法

    返回的EnumerableRowCollection<DataRow> 实现了 IEnumerable<T>接口。其中泛型参数T是DataRow。

    此对象可用在 LINQ表达式或方法查询中。

    语法:

    public static EnumerableRowCollection<DataRow> AsEnumerable (this DataTable source);

    在以下示例中,一个 DataColumn 数据表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);
    }

    注意:转成EnumerableRowCollection后,需要对两个这样的行集合进行操作,如:Distinct,Union,Except,Intesect,SequenceEqual都需要对数据源的元素进行相等比较,需要使用专门为Linq To Datatable新增加的DataRowComparer作为参数(实现了IEqulityComparer接口),用于比较DataRow的值(而不是引用比较)。否则,根本不能达到预期操作。

    IEnumerable<DataRow> distinctTable = table.AsEnumerable().Distinct(DataRowComparer.Default);

    2、Linq转DataTable

    (1)返回DataTable,其中包含的副本DataRow对象。

    public static DataTable CopyToDataTable<T> (this IEnumerable<T> source) where T : DataRow;

    以下示例查询 SalesOrderHeader 表的订单后 2001 年 8 月 8 日,并使用CopyToDataTable方法来创建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到指定的对象DataTable。

    public static void CopyToDataTable<T> (this IEnumerable<T> source, DataTable table, LoadOption options) where T : DataRow;

    LoadOption:当使用 LoadLoad 方法时控制数据源中的值如何应用至现有行。

    1. OverwriteChanges:    传入此行的值将同时写入每列数据的当前值和原始值版本。
    2. PreserveChanges:   传入此行的值将写入每列数据的原始值版本。 每列数据的当前版本不变化。 这是默认设置。
    3. Upsert  : 传入此行的值将写入每列数据的当前版本。 每列数据的原始版本不变化。

    以下示例:如果tableold表设置了主键,则可以合并记录,否则追加。

    table.AsEnumerable().CopyToDataTable(tableold,LoadOption.OverwriteChanges);

    tips:默认情况下(没对表进行操作),数据行的Original版本是不存在的,视图访问将报错。可以在访问之前使用DataRow.HasVersion来判断,也可以通过调用DataRow.AcceptChanges()方法来建立Original版本,避免异常发生。

    二、DataRow中的扩展方法:

    (1)获取字段值

    Field:提供对 DataRow 中的每个列值的强类型访问。

    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)设置字段值

    Set​Field:为 DataRow 中的指定列设置一个新值。

    public static void SetField<T> (DataRow row, string columnName, T value);

    如果value是null,则SetField方法转换null值设置为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:00

    2、分组:

    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分组,获取倒数第二条信息

    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:00

    3、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));
  • 相关阅读:
    冲刺博客 五
    冲刺博客 四
    冲刺第一天
    软件工程概论第十周学习进度
    软件工程概论第九周学习进度
    找水王
    软件工程概论第八周学习进度
    软件工程概论第七周学习进度
    四则运算最终版
    二维数组最大值
  • 原文地址:https://www.cnblogs.com/springsnow/p/9433933.html
Copyright © 2020-2023  润新知