Domanda

I must load a large set of data from SQL Server with ado.net.

This data returned from a slow stored procedure. I can't store result in temporary table because I don't know structure of result table. So I cannot do something like:

CREATE TABLE #temp
(
   ID INT,
   NAME VARCHAR(100),
   ...
)
INSERT INTO #temp Exec dbo.proc @param=1

SELECT COUNT(*) FROM #temp

SELECT * FROM #temp 

So as the data set is large, I use a SqlDataReader. But for progress I should know count of row for this data.

    private SqlCommand _asyncCmd;
    private SqlDataReader _reader;
    private SqlConnection _con;
    private IAsyncResult _asyncResult;

    public void GetDictionaryMetadataAsync(int param)
    {
        _con = new SqlConnection(_connectionString);
        _asyncCmd = new SqlCommand("SP_procedure", _con);

        _asyncCmd.CommandType = CommandType.StoredProcedure;
        _asyncCmd.CommandTimeout = 0;
        _asyncCmd.Parameters.Add(new SqlParameter("@param", SqlDbType.Int));
        _asyncCmd.Parameters["@param"].Value = param;

        _asyncCmd.Connection.Open();

        var callback = new AsyncCallback(EndExecuteReader);
        _asyncResult = _asyncCmd.BeginExecuteReader(callback, _asyncCmd);
    }

    private void EndExecuteReader(IAsyncResult result) 
    {
        _reader = _asyncCmd.EndExecuteReader(result);

        var command = new SqlCommand("SELECT @@ROWCOUNT", _con);
        // GETTING COUNT
        var count = command.ExecuteScalar() as int?;
        if (!count.HasValue) throw new NullReferenceException();
        Count = count.Value;
    }

    public IEnumerable<object[]> GetDictionaryMetadataAsyncEnd()
    {
        _asyncResult.AsyncWaitHandle.WaitOne();

        if (!_reader.Read())
            yield break;
        var values = new object[_reader.FieldCount];

        _reader.GetValues(values);
        yield return values;

        while (_reader.Read())
        {
            _reader.GetValues(values);
            yield return values;
        }
    }

But this part of code

        // GETTING COUNT
        var count = command.ExecuteScalar() as int?;

return always 0.

Do you have any idea how can I do it?

Thanks in advance.

È stato utile?

Soluzione

The most probable reason reason you get @@ROWCOUNT = 0, is running command in a separate implicitely defined db transaction (check the @@SPID value to make sure).

The solution is using a single explicitly defined transaction within your c# code.

Notice, that "SET NOCOUNT ON" option within the stored procedure causes no effects to @@ROWCOUNT value:

The @@ROWCOUNT function is updated even when SET NOCOUNT is ON.

PS. "MultipleActiveResultSets=True" option for SqlConnection connection string helped

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top