所以我刚从亚马逊那里得到LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ)的推荐。
它说本书介绍了使用Linq的dynamic
关键字,这让我想到了:
对于你无法用Linq做的dynamic
关键字,你能做些什么样的超赞呢?
答案 0 :(得分:20)
这是一个想法:通过将LINQ与动态相结合,您可以像输入类型一样查询无类型数据集。
例如,假设myDataSet是无类型的DataSet。使用动态类型和名为AsDynamic()的扩展方法,可以实现以下功能:
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<dynamic> 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<string> GetDynamicMemberNames()
{
return _row.Table.Columns.Cast<DataColumn>().Select (dc => dc.ColumnName);
}
}
}
通过继承DynamicObject,这利用了自定义绑定 - 您可以自己接管解析成员名称的过程。在这种情况下,我们将get和set成员访问绑定到底层DataRow中检索或存储对象。
答案 1 :(得分:3)
乔的回答很酷。我知道如何简化使用。如果将其添加到扩展类:
public static class Extensions
{
public static IEnumerable<dynamic> 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();
}
<强> N.B:强> 您需要添加以下参考:
System.Data.OleDb
程序集中的System.Data
添加到查询属性将System.Dynamic
添加到查询属性
uq.Connection
仅在通过“连接”下拉列表关联数据库时可用。如果您选择了"<none>"
,则会发生编译错误。
<强>更新强>
我注意到Joe在latest Beta v4.53.03 of LinqPad中添加了一个函数ExecuteQueryDynamic
,可用于实现此目的,例如:
void Main()
{
var q=this.ExecuteQueryDynamic("select * from Customers");
q.Dump();
}
这将使用Linq2Sql连接将Customers
表从Northwind数据库返回为IEnumerable<dynamic>
。
答案 2 :(得分:0)
我所做的让我得到结果的是这个,但我认为有更好的方法。
using (SqlConnection connection = new SqlConnection(this.Connection.ConnectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(query, connection);
SqlDataReader reader = command.ExecuteReader();
reader.Cast<IDataRecord>().AsQueryable().Dump();
}