【问题标题】:Nice examples of using .NET 4 dynamic keyword with Linq?在 Linq 中使用 .NET 4 动态关键字的好例子?
【发布时间】:2011-05-06 06:52:24
【问题描述】:

所以我刚从亚马逊那里得到了LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ) 的推荐。

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

你可以用dynamic 关键字做哪些你不能用其他方式用 Linq 做的很棒的事情?

【问题讨论】:

  • 如果我对动态对象执行 Linq 查询,我会得到 error CS1979: Query expressions over source type 'dynamic' or with a join sequence of type 'dynamic' are not allowed :S。
  • 对当前使用动态 LINQ 的限制以及解决这些限制的一些方法进行一些解读:weblogs.asp.net/davidfowler/archive/2010/08/04/…

标签: c# linq dynamic .net-4.0


【解决方案1】:

这里有一个想法:通过将 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 中检索或存储对象。

【讨论】:

  • 太棒了!当我看到这个时,我想添加一个 .ExecuteSql 扩展方法,它允许直接使用 LinqPad 与 SQL 服务器连接。 Check it out...
  • 虽然我现在已经习惯了并且感觉很自然,但我内心有一种纯粹主义者,这让我相信AsDynamic 应该被理想地命名为ToDynamicTo 表示身份更改转换,而 As 原生表示保留表示转换,如关键字as。但不管怎样,.NET 有很多类似的Ass,比如AsReadOnly
【解决方案2】:

乔的回答很酷。我有一个想法如何简化使用。如果将其添加到扩展类中:

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();      
}

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

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

  • uq.Connection 仅在您通过“连接”下拉列表关联数据库时可用。如果选择了"&lt;none&gt;",会出现编译错误。


更新: 我注意到乔在latest Beta v4.53.03 of LinqPad中添加了一个函数ExecuteQueryDynamic,可以用来实现这个,例如:

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

这将使用 Linq2Sql 连接从 Northwind 数据库中以 IEnumerable&lt;dynamic&gt; 的形式返回 Customers 表。

【讨论】:

    【解决方案3】:

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

     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();      
    }
    

    【讨论】:

      猜你喜欢
      • 2014-03-17
      • 2015-07-01
      • 2010-10-01
      • 1970-01-01
      • 2013-06-16
      • 2011-07-06
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多