Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dapper - reader.IsConsumed is false even after reading the last resultset #469

Open
minteractive opened this issue Feb 23, 2016 · 9 comments
Labels

Comments

@minteractive
Copy link

I am using Dapper version 1.42.0 and SQL Server as the back end to read multiple result-set by executing a Stored Procedure. The issue is that the IsConsumed property of the reader object is false when the last result-set uses spiltOn option to create multiple objects.

This isn't an issue most of the time as this occurs on the result-set, but in my case I have three result sets in which the last set is optional and the 2nd set uses splitOn option to create multiple objects. I use the reader.IsConsumed to determine whether to Read the last result-set or not and in cases when the stored procedure returns only 2 sets I receive an ObjectDisposed error when the code proceeds to read the 3rd set

@mgravell
Copy link
Member

Can I assume this ties into
http://stackoverflow.com/questions/35554284/reader-isconsumed-is-false-but-object-was-disposed/
?

I will try to repro. Do you have a short but complete example I can use to
show the error?
On 23 Feb 2016 4:38 p.m., "minteractive" notifications@github.com wrote:

I am using Dapper version 1.42.0 and SQL Server as the back end to read
multiple result-set by executing a Stored Procedure. The issue is that the
IsConsumed property of the reader object is false when the last result-set
uses spiltOn option to create multiple objects.

This isn't an issue most of the time as this occurs on the result-set, but
in my case I have three result sets in which the last set is optional and
the 2nd set uses splitOn option to create multiple objects. I use the
reader.IsConsumed to determine whether to Read the last result-set or not
and in cases when the store procedure returns only 2 sets I receive an
ObjectDisposed error...


Reply to this email directly or view it on GitHub
#469.

@minteractive
Copy link
Author

Yes, Below is the sample code I am using to execute the stored procedure,

using (var results = await DbContext.Database.Connection.QueryMultipleAsync("StoredProcedure", parameters, commandType: CommandType.StoredProcedure))
{
    IEnumerable<POCO1> collection1 = await results.ReadAsync<POCO1>();
    IEnumerable<POCO2> collection2 = results.Read<POCO2, Class1, Class2,POCO2>
    (
    (obj, obj1, obj2)
    {
        obj.Prop1 = obj1;
        obj.Prop2 = obj2;
    }, "Col1, Col2");
    //results.IsConsumed is set to false when the procedure returns only two sets.
    if (!results.IsConsumed)
    {
        IEnumerable <POCO3> collection3 = await results.ReadAsync<POCO3>();
    }
}

@mgravell
Copy link
Member

Just looking at the code: try adding .ToList() to the end of each of those
calls to Read / ReadAsync. IEnumerable is deferred execution. You need to
consume it now.

Note: for async, the pattern is:

var foo = (await someMethod(...)).ToList()

Meaning: you await before you ToList
On 23 Feb 2016 7:01 pm, "minteractive" notifications@github.com wrote:

Yes, Below is the sample code I am using to execute the stored procedure,

using (var results = await
DbContext.Database.Connection.QueryMultipleAsync("StoredProcedure",
parameters, commandType: CommandType.StoredProcedure))
{
IEnumerable collection1 = await results.ReadAsync();
IEnumerable collection2 = results.Read
(
(obj, obj1, obj2)
{
obj.Prop1 = obj1;
obj.Prop2 = obj2;
}, "Col1, Col2");

//results.IsConsumed is set to false when the procedure returns only two sets.
if(!results.IsConsumed)
{
    IEnumerable<POCO3> collection3 = await results.ReadAsync<POCO3>();
}

}


Reply to this email directly or view it on GitHub
#469 (comment)
.

@minteractive
Copy link
Author

Thanks, I updated the code and converted that to a list

@mgravell
Copy link
Member

And... did that fix it? Or does the problem still occur with the ToList()
in place?
On 23 Feb 2016 8:04 pm, "minteractive" notifications@github.com wrote:

Thanks, I updated the code and converted that to a list


Reply to this email directly or view it on GitHub
#469 (comment)
.

@minteractive
Copy link
Author

The issue still occurs with ToList()

@mgravell
Copy link
Member

OK. I'll have a look and see if I can get a repro from your code
On 23 Feb 2016 9:52 p.m., "minteractive" notifications@github.com wrote:

The issue still occurs with ToList()


Reply to this email directly or view it on GitHub
#469 (comment)
.

@mank1504
Copy link

Hi all,
I just ran into this issue as well. Here's a sample of the code I'm using:

using (var multi = conn.QueryMultiple(sql, args, transaction)) { while (!multi.IsConsumed) { var keywords = multi.Read<int, CustomObject, CustomObject>((typeID, customObject) => { //Do magic... return customObject; }); } }

In digging through the source I think the issue comes in the SqlMapper.GridReader.cs in the NextResult() function. I'm thinking in the else statement, right after the Dispose() is called, the IsConsumed could be set to true. Or even put the IsConsumed = true in the Dispose() function.

Thoughts?

@NinoFloris
Copy link

Another place where IsConsumed is never set, MultiReadInternal<TReturn>(Type[] types, ...
https://github.com/StackExchange/Dapper/blob/master/Dapper/SqlMapper.GridReader.cs#L224

@NickCraver NickCraver added the bug label May 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants