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

发布于 2024-10-01 04:25:36 字数 302 浏览 1 评论 0原文

因此,我刚刚收到 Amazon 的推荐 使用 C# 4.0 的 LINQ to Objects:使用和扩展 LINQ to对象和并行 LINQ (PLINQ)

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

使用 dynamic 关键字可以做哪些你无法做到的令人敬畏的事情林克否则?

So I Just got a recommendation from Amazon for LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ).

It says that the book introduces using the dynamic keyword with Linq, which got me thinking:

What kind of awesomeness could you do with the dynamic keyword that you couldn't do with Linq otherwise?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情深已缘浅 2024-10-08 04:25:36

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

Here's an idea: by combining LINQ with dynamic, you can query untyped datasets as though they were typed.

For instance, suppose that myDataSet is an untyped DataSet. With dynamic typing and an extension method called AsDynamic(), the following is possible:

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

Here's how to define the AsDynamic extension method. Notice how it returns IEnumerable of dynamic, which makes it suitable for LINQ queries:

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

By subclassing DynamicObject, this takes advantage of custom binding - where you take over the process of resolving member names yourself. In this case, we bind the get and set member access to retrieving or storing objects in the underlying DataRow.

清风夜微凉 2024-10-08 04:25:36

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

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

NB :
您需要添加以下引用:

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

  • uq.Connection 仅当您通过 Connection 关联数据库时才可用下拉菜单。如果您选择了,则会发生编译错误。


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

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

这将从 Northwind 数据库返回 Customers 表作为 IEnumerable,使用 Linq2Sql联系。

Joe's answer is cool. I have an idea how to simplify the usage. If you add this to the extension class:

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

It allows to use queries like this in 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.:
You need to add the following references:

  • Add System.Data.OleDb from the System.Data assembly to the query properties
  • Add System.Dynamic to the query properties

  • uq.Connection is only available if you have associated a database via the Connection dropdown. If you have selected "<none>", a compile error will occur.


Update:
I noticed that Joe has added a function ExecuteQueryDynamic in the latest Beta v4.53.03 of LinqPad, which can be used to achieve this, for example:

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

This will return the Customers table from the Northwind database as IEnumerable<dynamic>, using a Linq2Sql connection.

薄情伤 2024-10-08 04:25:36

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

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

What I've done that gets me the result is this, but I would think there is a better way.

 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();      
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文