相对而言,LINQ TO DataSet是LINQ技术中最小的一块,虽然是DB中抽取出来的一个离线的操作模型,但毕竟对象也是个内存里面的object而已。所以和LINQ TO Object相比,大多数的操作都是一样的,不同只是要根据DataSet,DataTable的结构标明字段而已。下面简单的列出LINQ TO DataSet相比LINQ TO Object一些要注意的特色。
Query UnTyped DataSet
和一般的LINQ相比,query对象是untyped DataSet的时候,使用Field<T>和SetField<T>来读写不同的column字段,下面是一个简单的例子:
DataTable orders = ds.Tables["Orders"];
DataTable orderDetails = ds.Tables["OrderDetails"];
var query =
from o in orders.AsEnumerable()
where o.Field<DateTime>( "OrderDate" ).Year >= 1998
orderby o.Field<DateTime>( "OrderDate" ) descending
select o;
在这里大致要注意三点
1.因为untyped DataSet没有实现IEnumerable<T> 和 IQueryable<T>的interface,所以如果想把它作为一个可以查询的对象的话,要先用AsEnumerable() 或者AsQueryable()转换一下,将它转换成IEnumerable<T>或者IQueryable<T>对象才能用LINQ去查询。如:from o in orders.AsEnumerable()
2.一般是使用使用Field<T>(“Column A”)和SetField<T>(“Column A”)来读写不同的column字段对应的element,用它来访问相对于以前我们用ds.Tables["Orders"].Row[“RowA”][ “Column A”]的访问模式比起来,一个很大的好处就是可以避免null类型产生的exception。我们以前从DataSet里面取数据的时候,如果取的出来的是null,就会抛出exception,所以我们经常作类似if(ds.Tables["Orders"].Row[“RowA”][ “Column A”]!=null)的判断来包装我们进一步的逻辑处理,但是用Field<T>(“Column A”)就可以避免这种麻烦。因为Field<T>(“Column A”)是nullable的。这个特性的由来是<T>这个泛型的使用,比如你取int类型数据的时候,如果你觉得它可能是null,那你就可以用Field<int?>(“Column A”)去取,这样就可以避免了exception的抛出。
3 .Field<T>和SetField<T>是使用并不局限在LINQ 的query当中,在程序的其他地方也能使用,可以用它去替代以前的我们访问DataSet的方式,例如:
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">foreach( DataRow r in orderDetails.Rows ) {</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> if (r.Field<decimal>( "UnitPrice" ) < 10 ){</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> r.SetField<decimal>( "UnitPrice", 10 );</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> }</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">}</font></span> |
Query Typed DataSet
这就更加简单了。对于定义了类型的DataSet,我们可以象查询内存中一般的object那样去查询它。例如:
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">var query =</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> from o in ds.Orders</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> where o.OrderDate.Year >= 1998</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> orderby o.OrderDate descending</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> select new { o.OrderID, o.OrderDate,</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> Amount = o.GetOrder_DetailsRows().Sum(</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> od => od.UnitPrice * od.Quantity ) };</font></span> |
还有一个与untyped DataSet不同的地方是在查询它的时候不需要使用AsEnumerable() 或者AsQueryable()那样的转换方法了。因为所有定义好的DataSet都是继承了TypedTableBase<T>这个基类,而这个基类已经实现了IEnumerable<T>的interface
Query DataSet中的relation
DataSet当中有时候也是有relation的,和DB一样,例如在下面的DataSet中加入relation:
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">DataTable orders = ds.Tables["Orders"];</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">DataTable orderDetails = ds.Tables["OrderDetails"];</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">ds.Relations.Add( "OrderDetails",</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> orders.Columns["OrderID"],</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> orderDetails.Columns["OrderID"]);</font></span> |
如果我们想像在LINQ TO SQL里面一样通过relation来访问与其有相关关系的table,可以使用GetChildRows方法来取得与当前table相关联的那个table里面的DataRows,并将其返回为可以查询的IQueryable<T>对象。例如:
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2">var query =</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> from o in orders.AsEnumerable()</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> where o.Field<DateTime>( "OrderDate" ).Year >= 1998</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> orderby o.Field<DateTime>( "OrderDate" ) descending</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> select new { OrderID = o.Field<int>( "OrderID" ),</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> OrderDate = o.Field<DateTime>( "OrderDate" ),</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> Amount = o.<strong>GetChildRows</strong>( "OrderDetails" ).Sum(</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> od => od.Field<decimal>( "UnitPrice" )</font></span> |
1 |
<span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; "><font size="2"> * od.Field<short>( "Quantity" ) ) };</font></span> |
这样我们就能通过relation来访问对象table了。
http://www.cnblogs.com/ruciffa/archive/2008/03/08/1096007.html