在Linq中使用.NET 4动态关键字的好例子?

所以我刚从亚马逊获得了使用C#4.0的LINQ to Objects的推荐:使用和扩展LINQ到对象和并行LINQ(PLINQ) 。

它说这本书介绍了使用Linq的dynamic关键字,这让我想到:

使用Linq无法做到的dynamic关键字可以做什么样的精彩呢?

这是一个想法:通过将LINQ与动态相结合,您可以像输入类型一样查询无类型数据集。

例如,假设myDataSet是无类型的DataSet。 通过动态类型和名为AsDynamic()的扩展方法,可以实现以下function:

 var query = from cust in myDataSet.Tables[0].AsDynamic() where cust.LastName.StartsWith ("A") orderby cust.LastName, cust.FirstName select new { cust.ID, cust.LastName, cust.FirstName, cust.BirthDate }; 

以下是如何定义AsDynamic扩展方法。 注意它如何返回动态的IEnumerable,这使它适用于LINQ查询:

 public static class Extensions { public static IEnumerable AsDynamic (this DataTable dt) { foreach (DataRow row in dt.Rows) yield return row.AsDynamic(); } public static dynamic AsDynamic (this DataRow row) { return new DynamicDataRow (row); } class DynamicDataRow : DynamicObject { DataRow _row; public DynamicDataRow (DataRow row) { _row = row; } public override bool TryGetMember (GetMemberBinder binder, out object result) { result = _row[binder.Name]; return true; } public override bool TrySetMember (SetMemberBinder binder, object value) { _row[binder.Name] = value; return true; } public override IEnumerable GetDynamicMemberNames() { return _row.Table.Columns.Cast().Select (dc => dc.ColumnName); } } } 

通过inheritanceDynamicObject,这利用了自定义绑定 – 您可以自己接管解析成员名称的过程。 在这种情况下,我们将get和set成员访问绑定到在底层DataRow中检索或存储对象。

乔的回答很酷。 我知道如何简化使用。 如果将其添加到扩展类:

 public static class Extensions { public static IEnumerable ExecuteSql(this UserQuery uq, string sql) { var connStr="Provider=SQLOLEDB.1;"+uq.Connection.ConnectionString; OleDbConnection connection = new OleDbConnection(connStr); DataSet myDataSet = new DataSet(); connection.Open(); OleDbDataAdapter DBAdapter = new OleDbDataAdapter(); DBAdapter.SelectCommand = new OleDbCommand(sql, connection); DBAdapter.Fill(myDataSet); var result = myDataSet.Tables[0].AsDynamic(); return result; } } 

它允许在LINQPad中使用这样的查询:

 void Main() { var query1 = from cust in this.ExecuteSql("SELECT * from Customers") where cust.ContactName.StartsWith ("C") orderby cust.ContactName select new { cust.CustomerID, cust.ContactName, cust.City }; query1.Dump(); } 

注意:您需要添加以下引用:

  • System.Data.OleDbSystem.Data程序集添加到查询属性
  • System.Dynamic添加到查询属性

  • uq.Connection仅在通过“连接”下拉列表关联数据库时可用。 如果选择了"" ,则会发生编译错误。


更新:我注意到Joe在LinqPad的最新Beta v4.53.03中添加了一个函数ExecuteQueryDynamic ,可用于实现此目的,例如:

 void Main() { var q=this.ExecuteQueryDynamic("select * from Customers"); q.Dump(); } 

这将使用Linq2Sql连接将来自Northwind数据库的Customers表作为IEnumerable返回。

我所做的让我得到的结果就是这个,但我认为有更好的方法。

  using (SqlConnection connection = new SqlConnection(this.Connection.ConnectionString)) { connection.Open(); SqlCommand command = new SqlCommand(query, connection); SqlDataReader reader = command.ExecuteReader(); reader.Cast().AsQueryable().Dump(); }