DataTable (Select, Find, Compute and Linq)

DataTable

Insert Data into DataTable

/*--------------------方法1--------------------*/
DataTable table = new DataTable();
table.Columns.Add("key", typeof(int));
table.Columns.Add("value", typeof(string));
table.Columns.Add("date", typeof(DateTime));
DataRow dr;
for (int i = 0; i <= 2; i++)
{
    dr = table.NewRow();
    dr["key"] = "key" + i;
    dr["value"] = i ;
    dr["date"] = DateTime.Now;
    table.Rows.Add(dr);
}

// Set Key
DataColumn[] keys = new DataColumn[] { table.Columns[0], table.Columns[2] };
table.PrimaryKey = keys;

/*--------------------方法2--------------------*/
DataTable table = new DataTable();
table.Columns.Add("key", typeof(int));
table.Columns.Add("value", typeof(string));
table.Columns.Add("date", typeof(DateTime));

// LoadDataRow, true 表示該 Row 資料可被修改
table.LoadDataRow(new object[] { "key0", 1,  DateTime.Now }, true); //key0, 0, 2012/12/12 下午 05:33:26
table.LoadDataRow(new object[] { "key1", 2,  DateTime.Now }, true); //key1, 1, 2012/12/12 下午 05:33:26
table.LoadDataRow(new object[] { "key2", 3,  DateTime.Now }, true); //key2, 2, 2012/12/12 下午 05:33:26

// Set Key
DataColumn[] keys = new DataColumn[] { table.Columns[0], table.Columns[2] };
table.PrimaryKey = keys;

Update Data on DataTable

//or
tables.Rows[0][1] = "123";

//有 Table Name ex.
tables["tableName"].Rows[0]["columnName"] = "123";

一般來說, DataTable.Find 與 Dictionary 搜尋速度差不多, Linq 速度稍慢, DataTable.Select 最慢

比較各搜尋速度參考:

http://www.dotblogs.com.tw/ian/archive/2012/10/23/78806.aspx

http://frankiestudy.blogspot.tw/2011/06/datatable.html

DataTable.Select

DataRow[] rows;
rows = table.Select("", "key desc"); //參數1 = where condition, 參數2 = order by
object[] objRow1 = row[0].ItemArray; //key2, 2, 2012/12/12 下午 05:33:26
object[] objRow2 = row[1].ItemArray; //key1, 1, 2012/12/12 下午 05:33:26
object[] objRow3 = row[2].ItemArray; //key0, 0, 2012/12/12 下午 05:33:26

/* (2) 有條件*/
DataRow[] foundRows;
foundRows = table.Select("key='key0' and value=0", "key desc");
object[] objRow1 = foundRows[0].ItemArray; //key0, 0, 2012/12/12 下午 05:33:26

DataTable.Find (只能查詢 PK 欄位)

rows = table.Rows.Find("key2"); //只能在key的欄位下查詢
object[] objRow1 = row[0].ItemArray; //key2, 2, 2012/12/12 下午 05:33:26

Linq query on DataTable

    
var query = from myRow in table.AsEnumerable()
             where myRow.Field<int>("value") > 0
             orderby myRow.Field<int>("value")
             select myRow; // select myRow 等於 select *

DataRow[] rows = query.ToArray();
// DataRow.ItemArray 將 DataRow 轉成 Object.Array
object[] objRow1 = rows[0].ItemArray; //key0, 0, 2012/12/12 下午 05:33:26
object[] objRow2 = rows[1].ItemArray; //key1, 1, 2012/12/12 下午 05:33:26
object[] objRow3 = rows[2].ItemArray; //key2, 2, 2012/12/12 下午 05:33:26

//也可以將 query 後的資料再塞入 DataTable 中
DataTable subDataTable = query.CopyToDataTable();

/* (2) 搜尋部分欄位(相當於 select *) */
var query = from myRow in table.AsEnumerable()
                   where myRow.Field<int>("value") > 0
                   select new
                  {
                       key = myRow.Field<string>("key"),
                       value = myRow.Field<int>("value"),
                       //date = myRow.Field<DateTime>("date")
                  };

DataRow[] rows = query.ToArray();
// DataRow.ItemArray 將 DataRow 轉成 Object.Array
object[] objRow1 = rows[0].ItemArray; //key0, 0
object[] objRow2 = rows[1].ItemArray; //key1, 1
object[] objRow3 = rows[2].ItemArray; //key2, 2

// 方法(2) 無法使用 .CopyToDataTable() , 會出現 error
DataTable subDataTable = query.CopyToDataTable();

DataTable.Compute (轉貼至http://www.dotblogs.com.tw/joysdw12/archive/2010/11/09/19294.aspx)

DataTable table = new DataTable();
table.Columns.Add("key", typeof(string));
table.Columns.Add("value", typeof(int));
table.Columns.Add("date", typeof(DateTime));
DataRow dr;
for (int i = 0; i <= 2; i++)
{
    dr = table.NewRow();
    dr["key"] = "key" + i;
    dr["value"] = i;
    dr["date"] = DateTime.Now;//.AddYears(i).Date;
    table.Rows.Add(dr);
}

DataColumn[] keys = new DataColumn[1];
keys[0] = table.Columns[0];
table.PrimaryKey = keys;


/******************************************
 * 常數計算 DataTable.Compute 方法
 * 參數:
 *      expression:要計算的運算式。
 *      filter:要限制在運算式中評估之資料列的篩選條件。
 * ****************************************/

// 加總運算 
object testVar = table.Compute("1 + 1", "");
Console.WriteLine("加總運算:" + testVar.ToString() + "");   // result = 2;

// 加總運算,無filter
testVar = table.Compute("1 + 1", "false");
Console.WriteLine("加總運算,無filter:" + testVar.ToString() + "");   // result = 2;

// 絕對值運算
testVar = table.Compute("abs(1)", "");
Console.WriteLine("絕對值運算:" + testVar.ToString() + "");   // result = null;

// 求餘數運算
testVar = table.Compute(" 2%2 ", "");
Console.WriteLine("求餘數運算" + testVar.ToString() + "");   // result = 0;

// 加法運算,exception: 無法評估。運算式 'System.Data.NameNode' 不是彙總。
//testVar = table.Compute("value+1", "true"); 
//Console.WriteLine(testVar.ToString() + "");

/******************************************
 * 彙總計算 DataTable.Compute 方法
 * 參數:
 *      expression:要計算的運算式。
 *      filter:要限制在運算式中評估之資料列的篩選條件。
 * ****************************************/

// 筆數計算
testVar = table.Compute("count(key)", "");
Console.WriteLine("筆數計算:" + testVar.ToString() + "");   // result = 3;

// 筆數計算,有filter
testVar = table.Compute("count(key)", "key='key1'");
Console.WriteLine("筆數計算,有filter:" + testVar.ToString() + "");   // result = 1;

// 欄位總和計算
testVar = table.Compute("sum(value)", "");
Console.WriteLine("欄位總和計算:" + testVar.ToString() + "");   // result = 1000;

// 欄位平均計算
testVar = table.Compute("avg(value)", "");
Console.WriteLine("欄位平均計算:" + testVar.ToString() + "");   // result = 200;

// 找出最小值
testVar = table.Compute("min(value)", "");
Console.WriteLine("找出最小值:" + testVar.ToString() + "");    // result = 0;

// 找出最大值
testVar = table.Compute("max(value)", "");
Console.WriteLine("找出最大值:" + testVar.ToString() + "");    // result = 400;

// 統計標準偏差
testVar = table.Compute("StDev(value)", "");
Console.WriteLine("統計標準偏差:" + testVar.ToString() + "");   // result = 158.113883008419;

// 統計方差
testVar = table.Compute("Var(value)", "");
Console.WriteLine("統計方差:" + testVar.ToString() + "");   // result = 25000;

// 複雜計算
testVar = table.Compute("max(value) / sum(value)", "");
Console.WriteLine("複雜計算:" + testVar.ToString() + "");   // result = 0.4;

/******************************************
* 欄位計算 DataColumn.Expression 屬性
* 屬性值:
*      運算式,用來計算資料行的值或建立彙總資料行。運算式的傳回型別是由資料行的 DataType 所判斷。
* ****************************************/

DataColumn column = new DataColumn("exp1", typeof(float));
table.Columns.Add(column);

// 乘法計算
column.Expression = "value*2";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("乘法計算:" + testVar.ToString() + ""); // result = 200;

// 字串長度計算函數
column.Expression = "len(key)";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("字串長度計算函數:" + testVar.ToString() + "");   // result = 4;

// 含空白字串長度計算函數
column.Expression = "len(' '+key+' ') ";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("含空白字串長度計算函數:" + testVar.ToString() + "");   // result = 6;

// 去空白後字串長度計算函數
column.Expression = "len(trim(' '+key+' '))";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("去空白後字串長度計算函數:" + testVar.ToString() + "");   // result = 4;

// 切字串函數 (SQL的Substring起始Index為1)
column.Expression = "substring(key,4,len(key)-3)";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("切字串函數:" + testVar.ToString() + "");   // result = 1;

// 資料型別轉換
column.Expression = "convert(substring(key,4,len(key)-3),'System.Int32')*1.6";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("資料型別轉換:" + testVar.ToString() + "");   // result = 1.6;

// SQL-ISNULL
column.Expression = "isnull(value,10)";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("SQL-ISNULL:" + testVar.ToString() + "");   // result = 100;

// CASE運算式
column.Expression = "iif(value>5,1000,2000)";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("CASE運算式" + testVar.ToString() + "");   // result = 1000;

// LINK運算式
column.Expression = "iif(key like '%1',1000,2000)";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("LINK運算式:" + testVar.ToString() + "");   // result = 1000;

// IN運算式
column.Expression = "iif(key not in('key1'),1000,2000)";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("IN運算式:" + testVar.ToString() + "");   // result = 2000;

// 多層三元運算
column.Expression = "iif(value>5,1000,iif(key like '%1',4000,2000))";
testVar = table.Select("key='key1'")[0]["exp1"];
Console.WriteLine("多層三元運算:" + testVar.ToString() + "");   // result = 1000;

/******************************************
* 資料查詢 DataTable.Select 方法
* 參數:
*      filterExpression:用來篩選資料列的準則。
*      sort:指定資料行和排序方向的字串。
* ****************************************/

DataRow[] row;

// 基本查詢
testVar = table.Select("key='key0'")[0]["key"].ToString();
Console.WriteLine("基本查詢:" + testVar.ToString() + "");   // result = key0;

// 多條件查詢
testVar = table.Select("key='key1' and value=100")[0]["key"].ToString();
Console.WriteLine("多條件查詢:" + testVar.ToString() + "");   // result = key1;

// DateTime日期查詢
string nowDate = DateTime.Now.ToString("#yyyy-MM-dd#");
testVar = table.Select("date=" + nowDate + "")[0]["key"].ToString();
Console.WriteLine("日期查詢:" + testVar.ToString() + "");   // result = key0;