[.NET]將DataTable中各2筆資料中去除DBNull然後合併
在論談上有看到「ADO.NET DATA TABLE」覺得蠻有趣的,所以就記錄下來。
主要DataTable中有ID, NAME, SURNAME等欄位,各筆資料中NAME或SURNAME有一個欄位是DBNull,然後希望可以將各2筆資料合併非DBNull的欄位,如下,
ID | NAME | SURNAME |
1 | DBNull | MIKE |
1 | JON | DBNull |
2 | DBNull | Berry |
2 | SON | DBNull |
合併之後如下,
ID | NAME | SURNAME |
1 | JON | MIKE |
2 | SON | Berry |
Way1:VijayPatel 大大的作法是先將資料轉成ToList,然後再Group起來,如下,
DataTable dt = new DataTable("test");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("SURNAME", typeof(string));
dt.Rows.Add(1, DBNull.Value, "MIKE");
dt.Rows.Add(1, "JON", DBNull.Value);
dt.Rows.Add(2, DBNull.Value, "Berry");
dt.Rows.Add(2, "SON", DBNull.Value);
//先轉成List
var collection = dt.AsEnumerable()
.Select(x => new
{
ID = x["ID"],
Name = x["NAME"],
SURNAME = x["SURNAME"]
}).ToList();
//然後再Group
var newCollection = collection.GroupBy(x => x.ID).Select(x => new
{
ID = x.Key,
Name = x.First(y => !string.IsNullOrWhiteSpace(y.Name.ToString())).Name.ToString(),
SURNAME = x.First(y => !string.IsNullOrWhiteSpace(y.SURNAME.ToString())).SURNAME.ToString()
}).ToList();
Way2:以類似SubQuery的方式來找出有值的欄位,然後再Distinct,如下,
DataTable dt = new DataTable("test");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("SURNAME", typeof(string));
dt.Rows.Add(1, DBNull.Value, "MIKE");
dt.Rows.Add(1, "JON", DBNull.Value);
dt.Rows.Add(2, DBNull.Value, "Berry");
dt.Rows.Add(2, "SON", DBNull.Value);
//SubQuery的方式來找出有值的欄位,然後再Distinct
var collection3 = dt.AsEnumerable()
.Select(x => new
{
ID = x["ID"],
Name = dt.AsEnumerable()
.Where(y =>!string.IsNullOrWhiteSpace(y["NAME"].ToString()) && x["ID"].ToString() == y["ID"].ToString() )
.Select(y => y["NAME"]).FirstOrDefault(),
SURNAME = dt.AsEnumerable()
.Where(y =>!string.IsNullOrWhiteSpace(y["SURNAME"].ToString()) && x["ID"].ToString() == y["ID"].ToString())
.Select(y => y["SURNAME"]).FirstOrDefault(),
}).Distinct().ToList();
Way3:以Self Join方式,過濾Null之後再Distinct,如下,
DataTable dt = new DataTable("test");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("SURNAME", typeof(string));
dt.Rows.Add(1, DBNull.Value, "MIKE");
dt.Rows.Add(1, "JON", DBNull.Value);
dt.Rows.Add(2, DBNull.Value, "Berry");
dt.Rows.Add(2, "SON", DBNull.Value);
//Self Join,過濾非Null之後再Distinct
var collection4 =
(from row1 in dt.AsEnumerable()
join row2 in dt.AsEnumerable()
on row1["ID"] equals row2["ID"]
select new
{
ID = row1["ID"] ,
NAME = row1.IsNull("NAME") ? row2["NAME"] : row1["NAME"],
SURNAME = row1.IsNull("SURNAME") ? row2["SURNAME"] : row1["SURNAME"]
}).Where(x => !string.IsNullOrEmpty(x.NAME.ToString()) && !string.IsNullOrEmpty(x.SURNAME.ToString()))
.Distinct();
Way4:簡化 VijayPatel 大大,以Group並依First中的Filter去取出第1個有值的資料,如下,
DataTable dt = new DataTable("test");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("SURNAME", typeof(string));
dt.Rows.Add(1, DBNull.Value, "MIKE");
dt.Rows.Add(1, "JON", DBNull.Value);
dt.Rows.Add(2, DBNull.Value, "Berry");
dt.Rows.Add(2, "SON", DBNull.Value);
//以Group並依First中的Filter去取出第1個有值的資料
var collection5 =
from row in dt.AsEnumerable()
group row by row["ID"]
into g
select new
{
ID = g.Key,
NAME = g.First(y => !y.IsNull("NAME"))["NAME"],
SURNAME = g.First(y => !y.IsNull("SURNAME"))["SURNAME"]
};
不知大家是否有其他的方式呢?
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^