2009-11-27 24 views
5

Uygulamamda, farklı saklı yordamlar tarafından döndürülen kayıtların bir listesini görüntülemem gerekiyor. Her bir mağaza prosedürü farklı kayıt türleri döndürür (yani sütun sayısı ve sütun tipi farklıdır).C# işlevi, genel nesneler/varlıklar döndürecek işlev

Orijinal düşüncem, her kayıt türü için bir sınıf oluşturmak ve karşılık gelen saklı yordamı yürütün ve List < MyCustomClass> öğesini döndüren bir işlev oluşturmaktı. Böyle bir şey:

public class MyCustomClass1 
    { 
     public int Col1 { get; set; } //In reality the columns are NOT called Col1 and Col1 but have proper names 
     public int Col2 { get; set; } 
    } 

    public static List<MyCustomClass1> GetDataForReport1(int Param1) 
    { 

     List<MyCustomClass1> output = new List<MyCustomClass1>(); 

     using (SqlConnection cn = new SqlConnection("MyConnectionString")) 
     using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1; 

      SqlDataReader rdr=cmd.ExecuteReader(); 

      int Col1_Ordinal = rdr.GetOrdinal("Col1"); 
      int Col2_Ordinal = rdr.GetOrdinal("Col2"); 

      while (rdr.Read()) 
      { 
         output.Add(new MyCustomClass1 
         { 
          Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value, 
          Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value 
         }); 
      } 
      rdr.Close(); 
      } 

     return output; 

    } 

Bu çalışıyor ancak müvekkilimin kodunda bu kayıtların işlemek gerekmez olarak (sadece benim uygulama katmanında bir grafik kontrol etmelerini bağlamak gerekir) gerçekten değil Bunu gerçekten kullanamayacağım özel sınıflarla dolduracağım gibi yapmak için mantıklı ol.

public static DataTable GetDataForReport1(int Param1) 
    { 

     DataTable output = new DataTable(); 

     using (SqlConnection cn = new SqlConnection("MyConnectionString")) 
     using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1; 

      output.Load(cmd.ExecuteReader()); 
     } 

     return output; 

    } 

Bu benim uygulama katmanında kullanılacak olursa olsun kontrol bağlanabilen bir DataTable döndürür: Bunu yapan hile buldum. DataTable kullanmanın gerçekten gerekli olup olmadığını merak ediyorum.

public static List<object> GetDataForReport1(int Param1) 
    { 

     List<object> output = new List<object>(); 

     using (SqlConnection cn = new SqlConnection("MyConnectionString")) 
     using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1; 

      SqlDataReader rdr=cmd.ExecuteReader(); 

      int Col1_Ordinal = rdr.GetOrdinal("Col1"); 
      int Col2_Ordinal = rdr.GetOrdinal("Col2"); 

      while (rdr.Read()) 
      { 
         output.Add(new 
         { 
          Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value, 
          Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value 
         }); 
      } 
      rdr.Close(); 
      } 

     return output; 

    } 

Diğer fikirler:

Ben nesnelerin bir listesi anonim sınıfları kullanılarak oluşturulmuş dönmek olmaz mı? Temel olarak, sadece bir grafik kontrolüne bağlanabileceğim 'bir şey' döndürme işlevini istiyorum ve gerçekten kullanılamadıkları için özel sınıflar oluşturmak zorunda kalmamayı tercih ediyorum. En iyi yaklaşım ne olurdu?

+1

btw, SqlDataReader için en iyi uygulama sonraki kullanım şeklidir: using (var rdr = cmd.ExecuteReader() {while (rdr.Read() {..}} - böylece otomatik olarak kapatılacak (atılacak) – abatishchev

+0

Kuyu lekeli .. – Anthony

cevap

4

İyi haber şu: Bu, ilk kez entities vs datasets sorununu çözmedi. Kendi programlama deneyimimden daha eski bir tartışma. DTO'ları veya özel varlıkları yazmak istemiyorsanız, seçenekleriniz DataTables/DataSets'dir veya bu tekerleği yeniden başlatabilirsiniz. İlk sen olmazdın ve son olmayacaksın. DTO/Varlıkları için argüman, DataSets ile elde ettiğiniz performansa genel yükünüzün olmamasıdır. DataSet'ler, çeşitli sütunların veri türleri hakkında çok fazla bilgi saklamak zorundadır, vb ...

Özel bir şey yoluna giderseniz ve nesneniz için mutlu olursanız, bir şey, duymanızdan mutluluk duyarsınız. sprocs tarafından döndürülen sütun adlarıyla eşleşen özellik adları, sütunları özelliklerle eşleştirmek için GetOrdinal'i kullandığınız tüm bu GetDataForReport() eşleme işlevlerini yazmayı atlayabilirsiniz. Neyse ki, bazı akıllı maymunlar here numaralı meseleyi düzgün bir şekilde eleştirdiler.

DÜZENLEME: (Silverlight datagrids için veri setlerini bağlanma) bugün tamamen farklı bir sorun üzerinde araştırma ve dinamik olarak oluşturulan nesnelerin (IL kullanarak) bir IEnumerable IDictionary bir IEnumerable dönüştürmek için nasıl gösterir Vladimir Bodurov tarafından this article karşıdan karşıya geldi. Dinamik koleksiyonlar sorununuzu çözmek için IDictionary IEnumerable yerine bir datareader kabul etmek için uzantı yöntemini kolayca değiştirebilirsiniz. Oldukça havalı. Ben de, artık veri kümesine ya da özel varlıklara gerek duymayacağınızdan tam olarak neyin peşinde olduğunuzu düşünüyorum.Sonuçta, özel bir varlık koleksiyonuna sahip olursunuz, ancak gerçek sınıfları yazmanın yükünü kaybedersiniz. Eğer tembel değilseniz

, burada Vladimir'in sözlüğü koleksiyonuna bir DataReader döner bir yöntem var (aslında onun uzantısı yöntemi dönüştürme daha az verimli olduğunu): Anonim sınıfları kullanırsanız, hala her tanımlıyorsanız

public static IEnumerable<IDictionary> ToEnumerableDictionary(this IDataReader dataReader) 
{ 
    var list = new List<Dictionary<string, object>>(); 
    Dictionary<int, string> keys = null; 
    while (dataReader.Read()) 
    { 
     if(keys == null) 
     { 
      keys = new Dictionary<int, string>(); 
      for (var i = 0; i < dataReader.FieldCount; i++) 
       keys.Add(i, dataReader.GetName(i)); 
     } 
     var dictionary = keys.ToDictionary(ordinalKey => ordinalKey.Value, ordinalKey => dataReader[ordinalKey.Key]); 
     list.Add(dictionary); 
    } 
    return list.ToArray(); 
} 
+0

Ne demek istediğimi anlıyorum ama bence, aramızda bir yer var. Bu sadece 'özel varlıklar ya da veri kümesi' listesini iade etmem. 'Aynı zamanda jenerik nesnelerin bir listesini verebileceğimi de söylemiştim. List < object >) Bu şekilde, özel varlıkların bir listesi olmayacak ancak bir veri kümesi olmayacaktır. – Anthony

+0

.net 4 kullanıyorsanız, bir Liste kullanabilirsiniz. Dinamikleriniz gerçekte Expando nesneleridir (http://bit.ly/TDzbN). – grenade

+0

Makaleye bağlantı için teşekkürler. Tam olarak ihtiyacım olan şey gibi görünüyor ve gerçekten 'varlık veya veri kümesi' olmayan bir çözüm getirecekti. Maalesef .net 4 kullanmıyorum ama bu zihni tutacağım. – Anthony

1

Eğer XmlSerialize edecekseniz ve bunun verimli olmasını istiyorsanız, anonim olamazlar. Değişiklikleri geri gönderecek misin? Anonim sınıflar bunun için fazla kullanılmayacaktır.

Şebeke dışında kalan verilerle gerçekten bir şey yapmayacaksanız, bir DataTable sizin bağlamınız için iyi bir yanıt olabilir.

Genel olarak, eğer herhangi bir enteresan iş girişi varsa, sadece ızgaralar etrafında dolaşmak yerine Veri Transferi Nesneleri vb. Kullanıyor olmalısınız.

+0

Veriler geri dönmeyecek. Veri Tansfer Nesnesi kullanırsam, o zaman özel bir sınıf kullanmakla aynı değil midir? Her kayıt türü için bir DTO oluşturmam gerekecek. – Anthony

0

yazın. Yazma miktarını azaltmak için Tip Inference kullanacaksınız ve sınıf türü herhangi bir isim alanını karıştırmayacak.

Onları burada kullanmanın dezavantajı, onları yöntemden çıkarmak istediğinizdir. Siz de belirttiğiniz gibi, bunu yapmanın tek yolu onları objelere dökmektir, bu da tüm verilerini yansımadan erişilemez kılar! Bu verilerle hiçbir zaman işlem yapmayacak veya hesaplayacak mısın? Sütunlardan birini değer yerine resim olarak görüntüleyin veya bazı koşullara göre gizleyin? Tek bir şartlı ifadeye sahip olsanız bile, bunu anonim sınıf versiyonu ile yapmak, siz olmasaydı diledi.