2010-10-18 4 views
2

est la méthode d'extension permettant de convertir un lecteur de données en objet à l'aide de la classe "DataReaderInjection" basée sur l'injecteur de valeur OMU.Méthode d'extension IEnumerable et Datareader, suggestions requises

public static IEnumerable<T> MapTo<T>(this IDataReader reader) where T : new() { 
    return reader.MapTo<T>(null); 
} 

public static IEnumerable<T> MapTo<T>(this IDataReader reader, Action<IDataReader, T> customMappingFunction) where T : new() { 
    using (reader) 
     while (!reader.IsClosed && reader.Read()) { 
      var nextItem = new T(); 
      nextItem.InjectFrom<DataReaderInjection>(reader); 
      if (customMappingFunction != null) 
       customMappingFunction(reader, nextItem); 
      yield return nextItem; 
     } 
} 

cette méthode a un bug car une fois que vous appelez cette méthode et datareader est fermé, prochain appel retournerait un vide IEnumerable, Pour résoudre ce problème je l'ai changé le code ci-dessus à la suite.

public static class DataAccessExtensions 
{ 
    public static IEnumerable<T> MapTo<T>(this IDataReader reader) where T : new() { 
     return reader.MapTo<T>(null); 
    } 

    private static Dictionary<int, IEnumerable> dataReaderCache = new Dictionary<int, IEnumerable>(); 
    private static object lockObj = new object(); 

    public static IEnumerable<T> MapTo<T>(this IDataReader reader, Action<IDataReader, T> customMappingFunction) where T : new() { 
     lock (lockObj) 
     { 
      if (dataReaderCache.ContainsKey(reader.GetHashCode())) 
       return dataReaderCache[reader.GetHashCode()] as IEnumerable<T>; 
     } 
     List<T> finalList = new List<T>(); 
     using (reader) { 
      while (!reader.IsClosed && reader.Read()) { 
       var nextItem = new T(); 
       nextItem 
        .InjectFrom<DataReaderInjection>(reader); 
       if (customMappingFunction != null) 
        customMappingFunction(reader, nextItem); 
       finalList.Add(nextItem); 
      } 
     } 
     lock (lockObj) 
     { 
      dataReaderCache.Add(reader.GetHashCode(), finalList); 
     } 
     return finalList; 
    } 

}

Qu'est-ce que vous en pensez cela fonctionnera

+1

en appelant MapTo de manière répétée sur le lecteur de données indique une odeur de code! BTW, votre version alternative ne fonctionnera pas non plus que vous créez MappedObject chaque fois que MapTo est appelé. Donc, le second appel retournera l'énumérateur vide. – VinayC

+0

oui vinay vous avez raison mais il se comporte bizarre bien qu'il rende le dernier objet. Dans l'ensemble, ce code ne fonctionne pas. Je vais essayer de mettre le correctif de code. laissez-moi savoir si vous pensez que c'est juste – Mohit

Répondre

3

... cette méthode a un bug car une fois que vous appelez cette méthode et datareader est fermé, prochain appel retournerait un vide IEnumerable

Ce n'est pas un bogue, les gestionnaires de données sont des itérateurs uniquement en avant, vous ne pouvez les répéter qu'une seule fois. Si vous devez parcourir plus d'une fois les résultats, mettez en cache l'IEnumerable que vous renvoyez. La manière la plus simple de faire ceci est de l'envelopper dans un List<T>, ou vous pouvez le mettre en cache paresseusement en utilisant Rx's MemoizeAll()

+0

Merci Mauricio, va certainement regarder dans "MemoizeAll()" de Rx, j'ai eu ce que vous essayez de dire. Mais, je suis impatient de résoudre ce problème en écrivant du code personnalisé. – Mohit

Questions connexes