NHibernate - Stream large result sets?

Deadly 提交于 2019-12-11 06:26:34

问题


I have to read in a large record set, process it, then write it out to a flat file.

The large result set comes from a Stored Proc in SQL 2000.

I currently have:
var results = session.CreateSQLQuery("exec usp_SalesExtract").List();

I would like to be able to read the result set row by row, to reduce the memory foot print

Thanks


回答1:


NHibernate is not designed for that usage. Plus, you're not really using its features.

So, in this case, it's better to use raw ADO.NET.




回答2:


Why not just use SQL Server's bcp Utility: http://msdn.microsoft.com/en-us/library/aa174646%28SQL.80%29.aspx to write the file from the stored procedure. If you need to do logic on the data, modify the the procedure to do what your need.




回答3:


NHibernate doesn't allow to do it directly.

You can do it with ADO.NET SqlDataReader using session.Connection property:

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

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



回答4:


If you can query the data with Linq to NH you can stream the results with the following extension method (Pass ISessionImplementor in if you don't like the reflection hack):

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

You'll need to wrap it in a using statement to ensure the reader is closed:

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


来源:https://stackoverflow.com/questions/2897383/nhibernate-stream-large-result-sets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!