NHibernate - Поток больших наборов результатов? - PullRequest
1 голос
/ 24 мая 2010

Мне нужно прочитать большой набор записей, обработать его, а затем записать в плоский файл.

Большой набор результатов поступает из хранимого процесса в SQL 2000.

В настоящее время у меня есть:
var results = session.CreateSQLQuery ("exec usp_SalesExtract"). List ();

Я хотел бы иметь возможность читать набор результатов строка за строкой, чтобы уменьшить отпечаток памяти

Спасибо

Ответы [ 4 ]

3 голосов
/ 24 мая 2010

NHibernate не предназначен для такого использования. Кроме того, вы на самом деле не используете его функции.

Итак, в этом случае лучше использовать сырой ADO.NET.

3 голосов
/ 24 мая 2010

Почему бы просто не использовать утилиту bcp SQL Server: http://msdn.microsoft.com/en-us/library/aa174646%28SQL.80%29.aspx для записи файла из хранимой процедуры. Если вам необходимо выполнить логику с данными, измените процедуру, чтобы сделать то, что вам нужно.

1 голос
/ 24 мая 2010

NHibernate не позволяет делать это напрямую.

Вы можете сделать это с ADO.NET SqlDataReader, используя 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 голосов
/ 07 июля 2016

Если вы можете запросить данные с помощью Linq для NH, вы можете передать результаты с помощью следующего метода расширения (введите ISessionImplementor, если вам не нравится хак с отражением):

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

Вам нужно будет обернуть его в оператор использования, чтобы убедиться, что читатель закрыт:

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