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

xoshrz7s  于 2023-09-28  发布在  .NET
关注(0)|答案(3)|浏览(130)

所以我刚从亚马逊得到了LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ)的推荐。
它说这本书介绍了在Linq中使用dynamic关键字,这让我思考:
dynamic关键字能做什么,而用Linq却做不到呢?

k0pti3hp

k0pti3hp1#

我有个想法通过将LINQ与dynamic相结合,可以像查询类型化数据集一样查询非类型化数据集。
例如,假设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扩展方法。请注意它如何返回动态的IE,这使得它适合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中的对象。

ymzxtsji

ymzxtsji2#

乔的回答很酷。我有一个简化用法的主意。如果你把它添加到扩展类中:

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仅在通过Connection下拉列表关联了数据库时可用。如果选择了"<none>",则会发生编译错误。
    **更新:**我注意到Joe在latest Beta v4.53.03 of LinqPad中增加了一个函数ExecuteQueryDynamic,可以用来实现这一点,例如:
void Main()
{
    var q=this.ExecuteQueryDynamic("select * from Customers");
    q.Dump();
}

这将使用Linq2Sql连接从Northwind数据库返回Customers表,作为IEnumerable<dynamic>

bprjcwpo

bprjcwpo3#

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

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

相关问题