2010-05-24 8 views
1

Je dois lire un grand ensemble d'enregistrements, le traiter, puis l'écrire dans un fichier plat.NHibernate - Diffusion de grands ensembles de résultats?

Le grand jeu de résultats provient d'une procédure stockée dans SQL 2000.

J'ai actuellement.
résultats var = session.createSQLQuery ("exec usp_SalesExtract") Liste();

Je voudrais pouvoir lire le jeu de résultats ligne par ligne, pour réduire le pied de la mémoire d'impression

Merci

+0

pourquoi même utiliser NHibernate ou ADO.NET, ils ajoutent juste une couche de complexité et les frais généraux, lorsque SQL Server peut tout faire par lui-même avec bcp ou SSIS ??? –

Répondre

3

NHibernate n'a pas été conçu pour cet usage. De plus, vous n'utilisez pas vraiment ses fonctionnalités. Donc, dans ce cas, il est préférable d'utiliser ADO.NET brut.

+0

il serait préférable de simplement utiliser SQL Server, son travail consiste à gérer de grands ensembles de résultats. –

3

Pourquoi ne pas simplement utiliser l'utilitaire bcp de SQL Server: http://msdn.microsoft.com/en-us/library/aa174646%28SQL.80%29.aspx pour écrire le fichier de la procédure stockée. Si vous avez besoin de faire de la logique sur les données, modifiez la procédure pour faire ce que vous avez besoin. NHibernate ne permet pas de le faire directement.

1

Vous pouvez le faire avec ADO.NET SqlDataReader en utilisant la propriété session.Connection:

SqlCommand MyCommand = new SqlCommand("sp_SalesExtract", session.Connection); 
MyCommand.CommandType = CommandType.StoredProcedure; 
SqlDataReader MyDataReader = MyCommand.ExecuteReader(); 

while (MyDataReader.Read()) 
{ 
    // handle row data (MyDataReader[0] ...) 
} 
0

Si vous pouvez interroger les données avec LINQ NH vous pouvez diffuser les résultats avec la méthode d'extension suivante (Passez ISessionImplementor si vous n'aimez pas le hack de réflexion):

public static EnumerableImpl Stream<T>(this IQueryable<T> source) 
{ 
    var provider = ((NhQueryable<T>) source).Provider as DefaultQueryProvider; 
    var sessionImpl = (ISessionImplementor)provider.GetType() 
     .GetProperty("Session", BindingFlags.NonPublic | 
      BindingFlags.Instance).GetValue(provider); 
    var expression = new NhLinqExpression(source.Expression, sessionImpl.Factory); 
    var query = sessionImpl.CreateQuery(expression); 
    query.SetParameters(expression.ParameterValuesByName); 
    provider.SetResultTransformerAndAdditionalCriteria(
     query, expression, expression.ParameterValuesByName); 
    return (EnumerableImpl)((AbstractQueryImpl2)query).Enumerable(); 
} 

private static void SetParameters(this IQuery query, 
    IDictionary<string, Tuple<object, IType>> parameters) 
{ 
    foreach (var parameterName in query.NamedParameters) 
    { 
     var param = parameters[parameterName]; 
     if (param.Item1 == null) 
     { 
      if (typeof(IEnumerable).IsAssignableFrom(param.Item2.ReturnedClass) && 
       param.Item2.ReturnedClass != typeof(string)) 
       query.SetParameterList(parameterName, null, param.Item2); 
      else query.SetParameter(parameterName, null, param.Item2); 
     } 
     else 
     { 
      if (param.Item1 is IEnumerable && !(param.Item1 is string)) 
       query.SetParameterList(parameterName, (IEnumerable)param.Item1); 
      else if (param.Item2 != null) 
       query.SetParameter(parameterName, param.Item1, param.Item2); 
      else query.SetParameter(parameterName, param.Item1); 
     } 
    } 
} 

Vous aurez besoin l'envelopper dans une déclaration à l'aide pour que le lecteur est fermé:

using (var results = session.Query<Fark>().Take(50).Where(x => x.Enabled).Stream()) 
{ 
    results.ForEach(x => writer.WriteLine(x.ToCsv())); 
} 
Questions connexes