2010-11-07 18 views
17

Sadece Amazon'dan LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ) için bir öneri aldım.Linq ile .NET 4 dinamik anahtar sözcüğünü kullanmanın güzel örnekleri?

O kitap beni düşündürdü, hangi Linq ile dynamic anahtar kelimeyi kullanarak tanıtır söylüyor:

Eğer aksi Linq ile yapamadık dynamic anahtar kelime ile yapabilirdi harikaları ne tür?

+1

Ben dinamik nesne üzerinde bir Linq sorgusu yaparsanız, ben 'almak hata CS1979: kaynak türü üzerinden Sorgu ifadeleri 'dinamik' ya allowed' olmayan türü 'dinamik' bir katılmak dizisi ile: S. –

+0

Dinamikler ile LINQ kullanmanın mevcut sınırlamalarını ve etraflarında çalışmanın bazı yollarını biraz okuma: http://weblogs.asp.net/davidfowler/archive/2010/08/04/dynamic-linq-a-little- more-dynamic.aspx – egoodberry

cevap

20

İşte bir fikir: LINQ'yi dinamikle birleştirerek, yazılmamış veri kümelerini yazdıklarına benzer şekilde sorgulayabilirsiniz. Örneğin, benim DataSet'in bir türlenmemiş DataSet olduğunu varsayalım. Dinamik yazarak ve AsDynamic (denilen bir uzantısı yöntemiyle) ile aşağıdaki mümkündür:

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

İşte AsDynamic uzatma yöntemini tanımlamak nasıl. uygundur LINQ sorguları için yapar, bu dinamiğin IEnumerable döndürür nasıl Uyarı:

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 sınıflara olarak, bu özel bağlama yararlanır - Eğer üye adlarını kendiniz belirleme süreci devralacak nerede. Bu durumda, temel DataRow'daki nesneleri almak veya saklamak için get ve set üye erişimini bağlarız.

+0

Awsome! Bunu gördüğümde, LinqPad'i doğrudan SQL sunucu bağlantıları ile kullanmanıza izin veren bir .ExecuteSql uzantı yöntemi ekleme fikrim vardı. [Şuna bak ...] (http://stackoverflow.com/a/24885293/1016343) – Matt

+0

Şimdiye kadar alışkınım ve doğal olarak hissediyor olsam da, bana 'AsDynamic' inandıran bu saflık var. İdeal olarak 'ToDynamic' olarak adlandırılmalıdır. '' '' '' '' '' '', '' '', '' Anahtar kelimesi '' gibi '' doğal olarak '' dönüşüm korunmasını temsil eder. Ama yine de, .NET 'AsReadOnly' gibi As' birçok, benzer vardır. – nawfal

2

Joe'nun cevabı güzel. Kullanımın nasıl basitleştirileceğine dair bir fikrim var. Eğer uzatma sınıfına bu eklerseniz:

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

O LINQPad böyle sorguları kullanmanıza olanak sağlar:

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

Not: Aşağıdaki referanslar eklemem gerekiyor :

  • System.Data.OleDb,Bunu sağlamak için de kullanılabilir Joe latest Beta v4.53.03 of LinqPad bir işlev ExecuteQueryDynamic eklemiştir fark,: Sorgu özelliklerinemontaj
  • Güncelleme sorgu özellikleri

için System.Dynamic ekle örneğin:

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

Bu den Customers tablo döndürür Bir Linq2Sql bağlantısı kullanarak Northwind veritabanı IEnumerable<dynamic> olarak.

0

Yaptığım şey bana bu sonucu veriyor, ama daha iyi bir yol olduğunu düşünürdüm.

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