Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
Dapper
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
Dapper
Commits
d0f880d1
Commit
d0f880d1
authored
Aug 14, 2014
by
Marc Gravell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1.30: better async cancellation
parent
d3afa33f
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
255 additions
and
69 deletions
+255
-69
AssemblyInfo.cs
Dapper NET40/Properties/AssemblyInfo.cs
+2
-2
SqlMapper.cs
Dapper NET40/SqlMapper.cs
+30
-26
SqlMapperAsync.cs
Dapper NET45/SqlMapperAsync.cs
+163
-24
AssemblyInfo.cs
Dapper.Contrib.Tests/Properties/AssemblyInfo.cs
+2
-2
AssemblyInfo.cs
Dapper.Contrib/Properties/AssemblyInfo.cs
+2
-2
AssemblyInfo.cs
Dapper.SqlBuilder/Properties/AssemblyInfo.cs
+2
-2
AssemblyInfo.cs
DapperTests NET35/Properties/AssemblyInfo.cs
+2
-2
AssemblyInfo.cs
DapperTests NET45/Properties/AssemblyInfo.cs
+2
-2
Tests.cs
DapperTests NET45/Tests.cs
+46
-4
AssemblyInfo.cs
Tests/Properties/AssemblyInfo.cs
+2
-2
dapper.nuspec
dapper.nuspec
+2
-1
No files found.
Dapper NET40/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -32,5 +32,5 @@
...
@@ -32,5 +32,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
Dapper NET40/SqlMapper.cs
View file @
d0f880d1
...
@@ -1231,7 +1231,7 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
...
@@ -1231,7 +1231,7 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
)
)
{
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
return
ExecuteReaderImpl
(
cnn
,
ref
command
);
return
ExecuteReaderImpl
(
cnn
,
ref
command
,
CommandBehavior
.
Default
);
}
}
/// <summary>
/// <summary>
...
@@ -1244,7 +1244,19 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
...
@@ -1244,7 +1244,19 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
/// </remarks>
/// </remarks>
public
static
IDataReader
ExecuteReader
(
this
IDbConnection
cnn
,
CommandDefinition
command
)
public
static
IDataReader
ExecuteReader
(
this
IDbConnection
cnn
,
CommandDefinition
command
)
{
{
return
ExecuteReaderImpl
(
cnn
,
ref
command
);
return
ExecuteReaderImpl
(
cnn
,
ref
command
,
CommandBehavior
.
Default
);
}
/// <summary>
/// Execute parameterized SQL and return an <see cref="IDataReader"/>
/// </summary>
/// <returns>An <see cref="IDataReader"/> that can be used to iterate over the results of the SQL query.</returns>
/// <remarks>
/// This is typically used when the results of a query are not processed by Dapper, for example, used to fill a <see cref="DataTable"/>
/// or <see cref="DataSet"/>.
/// </remarks>
public
static
IDataReader
ExecuteReader
(
this
IDbConnection
cnn
,
CommandDefinition
command
,
CommandBehavior
commandBehavior
)
{
return
ExecuteReaderImpl
(
cnn
,
ref
command
,
commandBehavior
);
}
}
#if !CSHARP30
#if !CSHARP30
...
@@ -1385,7 +1397,7 @@ private static GridReader QueryMultipleImpl(this IDbConnection cnn, ref CommandD
...
@@ -1385,7 +1397,7 @@ private static GridReader QueryMultipleImpl(this IDbConnection cnn, ref CommandD
{
{
if
(
wasClosed
)
cnn
.
Open
();
if
(
wasClosed
)
cnn
.
Open
();
cmd
=
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
);
cmd
=
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
);
reader
=
cmd
.
ExecuteReader
(
wasClosed
?
CommandBehavior
.
CloseConnection
:
CommandBehavior
.
Default
);
reader
=
cmd
.
ExecuteReader
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
);
var
result
=
new
GridReader
(
cmd
,
reader
,
identity
);
var
result
=
new
GridReader
(
cmd
,
reader
,
identity
);
wasClosed
=
false
;
// *if* the connection was closed and we got this far, then we now have a reader
wasClosed
=
false
;
// *if* the connection was closed and we got this far, then we now have a reader
...
@@ -1423,7 +1435,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
...
@@ -1423,7 +1435,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
cmd
=
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
);
cmd
=
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
);
if
(
wasClosed
)
cnn
.
Open
();
if
(
wasClosed
)
cnn
.
Open
();
reader
=
cmd
.
ExecuteReader
(
wasClosed
?
CommandBehavior
.
CloseConnection
:
CommandBehavior
.
Default
);
reader
=
cmd
.
ExecuteReader
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
);
wasClosed
=
false
;
// *if* the connection was closed and we got this far, then we now have a reader
wasClosed
=
false
;
// *if* the connection was closed and we got this far, then we now have a reader
// with the CloseConnection flag, so the reader will deal with the connection; we
// with the CloseConnection flag, so the reader will deal with the connection; we
// still need something in the "finally" to ensure that broken SQL still results
// still need something in the "finally" to ensure that broken SQL still results
...
@@ -1657,7 +1669,7 @@ partial class DontMap { }
...
@@ -1657,7 +1669,7 @@ partial class DontMap { }
{
{
ownedCommand
=
command
.
SetupCommand
(
cnn
,
cinfo
.
ParamReader
);
ownedCommand
=
command
.
SetupCommand
(
cnn
,
cinfo
.
ParamReader
);
if
(
wasClosed
)
cnn
.
Open
();
if
(
wasClosed
)
cnn
.
Open
();
ownedReader
=
ownedCommand
.
ExecuteReader
();
ownedReader
=
ownedCommand
.
ExecuteReader
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
);
reader
=
ownedReader
;
reader
=
ownedReader
;
}
}
DeserializerState
deserializer
=
default
(
DeserializerState
);
DeserializerState
deserializer
=
default
(
DeserializerState
);
...
@@ -3008,7 +3020,7 @@ private static T ExecuteScalarImpl<T>(IDbConnection cnn, ref CommandDefinition c
...
@@ -3008,7 +3020,7 @@ private static T ExecuteScalarImpl<T>(IDbConnection cnn, ref CommandDefinition c
return
Parse
<
T
>(
result
);
return
Parse
<
T
>(
result
);
}
}
private
static
IDataReader
ExecuteReaderImpl
(
IDbConnection
cnn
,
ref
CommandDefinition
command
)
private
static
IDataReader
ExecuteReaderImpl
(
IDbConnection
cnn
,
ref
CommandDefinition
command
,
CommandBehavior
commandBehavior
)
{
{
Action
<
IDbCommand
,
object
>
paramReader
=
GetParameterReader
(
cnn
,
ref
command
);
Action
<
IDbCommand
,
object
>
paramReader
=
GetParameterReader
(
cnn
,
ref
command
);
...
@@ -3018,8 +3030,9 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin
...
@@ -3018,8 +3030,9 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin
{
{
cmd
=
command
.
SetupCommand
(
cnn
,
paramReader
);
cmd
=
command
.
SetupCommand
(
cnn
,
paramReader
);
if
(
wasClosed
)
cnn
.
Open
();
if
(
wasClosed
)
cnn
.
Open
();
var
reader
=
cmd
.
ExecuteReader
(
wasClosed
?
CommandBehavior
.
CloseConnection
:
CommandBehavior
.
Default
);
if
(
wasClosed
)
commandBehavior
|=
CommandBehavior
.
CloseConnection
;
wasClosed
=
false
;
var
reader
=
cmd
.
ExecuteReader
(
commandBehavior
);
wasClosed
=
false
;
// don't dispose before giving it to them!
return
reader
;
return
reader
;
}
}
finally
finally
...
@@ -3733,7 +3746,7 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
...
@@ -3733,7 +3746,7 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
/// </summary>
/// </summary>
public
IEnumerable
<
dynamic
>
Read
(
bool
buffered
=
true
)
public
IEnumerable
<
dynamic
>
Read
(
bool
buffered
=
true
)
{
{
return
Read
<
DapperRow
>(
buffered
);
return
Read
Impl
<
dynamic
>(
typeof
(
DapperRow
),
buffered
);
}
}
#endif
#endif
...
@@ -3755,21 +3768,7 @@ public IEnumerable<T> Read<T>(bool buffered)
...
@@ -3755,21 +3768,7 @@ public IEnumerable<T> Read<T>(bool buffered)
public
IEnumerable
<
T
>
Read
<
T
>(
bool
buffered
=
true
)
public
IEnumerable
<
T
>
Read
<
T
>(
bool
buffered
=
true
)
#endif
#endif
{
{
if
(
reader
==
null
)
throw
new
ObjectDisposedException
(
GetType
().
FullName
,
"The reader has been disposed; this can happen after all data has been consumed"
);
return
ReadImpl
<
T
>(
typeof
(
T
),
buffered
);
if
(
consumed
)
throw
new
InvalidOperationException
(
"Query results must be consumed in the correct order, and each result can only be consumed once"
);
var
typedIdentity
=
identity
.
ForGrid
(
typeof
(
T
),
gridIndex
);
CacheInfo
cache
=
GetCacheInfo
(
typedIdentity
,
null
,
true
);
var
deserializer
=
cache
.
Deserializer
;
int
hash
=
GetColumnHash
(
reader
);
if
(
deserializer
.
Func
==
null
||
deserializer
.
Hash
!=
hash
)
{
deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
typeof
(
T
),
reader
,
0
,
-
1
,
false
));
cache
.
Deserializer
=
deserializer
;
}
consumed
=
true
;
var
result
=
ReadDeferred
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
return
buffered
?
result
.
ToList
()
:
result
;
}
}
/// <summary>
/// <summary>
...
@@ -3782,6 +3781,11 @@ public IEnumerable<object> Read(Type type, bool buffered = true)
...
@@ -3782,6 +3781,11 @@ public IEnumerable<object> Read(Type type, bool buffered = true)
#endif
#endif
{
{
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
return
ReadImpl
<
object
>(
type
,
buffered
);
}
private
IEnumerable
<
T
>
ReadImpl
<
T
>(
Type
type
,
bool
buffered
)
{
if
(
reader
==
null
)
throw
new
ObjectDisposedException
(
GetType
().
FullName
,
"The reader has been disposed; this can happen after all data has been consumed"
);
if
(
reader
==
null
)
throw
new
ObjectDisposedException
(
GetType
().
FullName
,
"The reader has been disposed; this can happen after all data has been consumed"
);
if
(
consumed
)
throw
new
InvalidOperationException
(
"Query results must be consumed in the correct order, and each result can only be consumed once"
);
if
(
consumed
)
throw
new
InvalidOperationException
(
"Query results must be consumed in the correct order, and each result can only be consumed once"
);
var
typedIdentity
=
identity
.
ForGrid
(
type
,
gridIndex
);
var
typedIdentity
=
identity
.
ForGrid
(
type
,
gridIndex
);
...
@@ -3795,10 +3799,11 @@ public IEnumerable<object> Read(Type type, bool buffered = true)
...
@@ -3795,10 +3799,11 @@ public IEnumerable<object> Read(Type type, bool buffered = true)
cache
.
Deserializer
=
deserializer
;
cache
.
Deserializer
=
deserializer
;
}
}
consumed
=
true
;
consumed
=
true
;
var
result
=
ReadDeferred
<
object
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
var
result
=
ReadDeferred
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
return
buffered
?
result
.
ToList
()
:
result
;
return
buffered
?
result
.
ToList
()
:
result
;
}
}
private
IEnumerable
<
TReturn
>
MultiReadInternal
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
Delegate
func
,
string
splitOn
)
private
IEnumerable
<
TReturn
>
MultiReadInternal
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
Delegate
func
,
string
splitOn
)
{
{
var
identity
=
this
.
identity
.
ForGrid
(
typeof
(
TReturn
),
new
Type
[]
{
var
identity
=
this
.
identity
.
ForGrid
(
typeof
(
TReturn
),
new
Type
[]
{
...
@@ -3965,7 +3970,6 @@ private void NextResult()
...
@@ -3965,7 +3970,6 @@ private void NextResult()
Dispose
();
Dispose
();
}
}
}
}
/// <summary>
/// <summary>
/// Dispose the grid, closing and disposing both the underlying reader and command.
/// Dispose the grid, closing and disposing both the underlying reader and command.
...
...
Dapper NET45/SqlMapperAsync.cs
View file @
d0f880d1
...
@@ -13,6 +13,23 @@ namespace Dapper
...
@@ -13,6 +13,23 @@ namespace Dapper
public
static
partial
class
SqlMapper
public
static
partial
class
SqlMapper
{
{
/// <summary>
/// Execute a query asynchronously using .NET 4.5 Task.
/// </summary>
public
static
Task
<
IEnumerable
<
dynamic
>>
QueryAsync
(
this
IDbConnection
cnn
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
)
{
return
QueryAsync
<
dynamic
>(
cnn
,
typeof
(
DapperRow
),
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
,
default
(
CancellationToken
)));
}
/// <summary>
/// Execute a query asynchronously using .NET 4.5 Task.
/// </summary>
public
static
Task
<
IEnumerable
<
dynamic
>>
QueryAsync
(
this
IDbConnection
cnn
,
CommandDefinition
command
)
{
return
QueryAsync
<
dynamic
>(
cnn
,
typeof
(
DapperRow
),
command
);
}
/// <summary>
/// <summary>
/// Execute a query asynchronously using .NET 4.5 Task.
/// Execute a query asynchronously using .NET 4.5 Task.
/// </summary>
/// </summary>
...
@@ -52,19 +69,49 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
...
@@ -52,19 +69,49 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
effectiveType
,
param
==
null
?
null
:
param
.
GetType
(),
null
);
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
effectiveType
,
param
==
null
?
null
:
param
.
GetType
(),
null
);
var
info
=
GetCacheInfo
(
identity
,
param
,
command
.
AddToCache
);
var
info
=
GetCacheInfo
(
identity
,
param
,
command
.
AddToCache
);
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
var
cancel
=
command
.
CancellationToken
;
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
{
{
DbDataReader
reader
=
null
;
try
try
{
{
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
cancel
).
ConfigureAwait
(
false
);
using
(
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
))
reader
=
await
cmd
.
ExecuteReaderAsync
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
,
cancel
).
ConfigureAwait
(
false
);
var
tuple
=
info
.
Deserializer
;
int
hash
=
GetColumnHash
(
reader
);
if
(
tuple
.
Func
==
null
||
tuple
.
Hash
!=
hash
)
{
tuple
=
info
.
Deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
effectiveType
,
reader
,
0
,
-
1
,
false
));
if
(
command
.
AddToCache
)
SetQueryCache
(
identity
,
info
);
}
var
func
=
tuple
.
Func
;
if
(
command
.
Buffered
)
{
List
<
T
>
buffer
=
new
List
<
T
>();
while
(
await
reader
.
ReadAsync
(
cancel
).
ConfigureAwait
(
false
))
{
buffer
.
Add
((
T
)
func
(
reader
));
}
return
buffer
;
}
else
{
{
return
ExecuteReader
<
T
>(
reader
,
effectiveType
,
identity
,
info
,
command
.
AddToCache
).
ToList
();
// can't use ReadAsync / cancellation; but this will have to do
wasClosed
=
false
;
// don't close if handing back an open reader; rely on the command-behavior
var
deferred
=
ExecuteReaderSync
<
T
>(
reader
,
func
);
reader
=
null
;
// to prevent it being disposed before the caller gets to see it
return
deferred
;
}
}
}
}
finally
finally
{
{
using
(
reader
)
{
}
// dispose if non-null
if
(
wasClosed
)
cnn
.
Close
();
if
(
wasClosed
)
cnn
.
Close
();
}
}
}
}
}
}
...
@@ -111,7 +158,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
...
@@ -111,7 +158,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
try
try
{
{
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
CacheInfo
info
=
null
;
CacheInfo
info
=
null
;
string
masterSql
=
null
;
string
masterSql
=
null
;
...
@@ -205,7 +252,7 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
...
@@ -205,7 +252,7 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
{
{
try
try
{
{
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
return
await
cmd
.
ExecuteNonQueryAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
return
await
cmd
.
ExecuteNonQueryAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
}
}
finally
finally
...
@@ -394,10 +441,11 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
...
@@ -394,10 +441,11 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
try
try
{
{
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
using
(
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
))
using
(
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
,
command
.
CancellationToken
).
ConfigureAwait
(
false
))
{
{
if
(!
command
.
Buffered
)
wasClosed
=
false
;
// handing back open reader; rely on command-behavior
var
results
=
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
default
(
CommandDefinition
),
map
,
splitOn
,
reader
,
identity
);
var
results
=
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
default
(
CommandDefinition
),
map
,
splitOn
,
reader
,
identity
);
return
command
.
Buffered
?
results
.
ToList
()
:
results
;
return
command
.
Buffered
?
results
.
ToList
()
:
results
;
}
}
...
@@ -407,18 +455,8 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
...
@@ -407,18 +455,8 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
}
}
}
}
private
static
IEnumerable
<
T
>
ExecuteReader
<
T
>(
IDataReader
reader
,
Type
effectiveType
,
Identity
identity
,
CacheInfo
info
,
bool
addToCache
)
private
static
IEnumerable
<
T
>
ExecuteReader
Sync
<
T
>(
IDataReader
reader
,
Func
<
IDataReader
,
object
>
func
)
{
{
var
tuple
=
info
.
Deserializer
;
int
hash
=
GetColumnHash
(
reader
);
if
(
tuple
.
Func
==
null
||
tuple
.
Hash
!=
hash
)
{
tuple
=
info
.
Deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
effectiveType
,
reader
,
0
,
-
1
,
false
));
if
(
addToCache
)
SetQueryCache
(
identity
,
info
);
}
var
func
=
tuple
.
Func
;
while
(
reader
.
Read
())
while
(
reader
.
Read
())
{
{
yield
return
(
T
)
func
(
reader
);
yield
return
(
T
)
func
(
reader
);
...
@@ -439,6 +477,107 @@ private static IEnumerable<T> ExecuteReader<T>(IDataReader reader, Type effectiv
...
@@ -439,6 +477,107 @@ private static IEnumerable<T> ExecuteReader<T>(IDataReader reader, Type effectiv
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
return
QueryMultipleAsync
(
cnn
,
command
);
return
QueryMultipleAsync
(
cnn
,
command
);
}
}
partial
class
GridReader
{
CancellationToken
cancel
;
internal
GridReader
(
IDbCommand
command
,
IDataReader
reader
,
Identity
identity
,
CancellationToken
cancel
)
:
this
(
command
,
reader
,
identity
)
{
this
.
cancel
=
cancel
;
}
/// <summary>
/// Read the next grid of results, returned as a dynamic object
/// </summary>
public
Task
<
IEnumerable
<
dynamic
>>
ReadAsync
(
bool
buffered
=
true
)
{
return
ReadAsyncImpl
<
dynamic
>(
typeof
(
DapperRow
),
buffered
);
}
/// <summary>
/// Read the next grid of results
/// </summary>
public
Task
<
IEnumerable
<
object
>>
ReadAsync
(
Type
type
,
bool
buffered
=
true
)
{
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
return
ReadAsyncImpl
<
object
>(
type
,
buffered
);
}
/// <summary>
/// Read the next grid of results
/// </summary>
public
Task
<
IEnumerable
<
T
>>
ReadAsync
<
T
>(
bool
buffered
=
true
)
{
return
ReadAsyncImpl
<
T
>(
typeof
(
T
),
buffered
);
}
private
async
Task
NextResultAsync
()
{
if
(
await
((
DbDataReader
)
reader
).
NextResultAsync
(
cancel
).
ConfigureAwait
(
false
))
{
readCount
++;
gridIndex
++;
consumed
=
false
;
}
else
{
// happy path; close the reader cleanly - no
// need for "Cancel" etc
reader
.
Dispose
();
reader
=
null
;
Dispose
();
}
}
private
Task
<
IEnumerable
<
T
>>
ReadAsyncImpl
<
T
>(
Type
type
,
bool
buffered
)
{
if
(
reader
==
null
)
throw
new
ObjectDisposedException
(
GetType
().
FullName
,
"The reader has been disposed; this can happen after all data has been consumed"
);
if
(
consumed
)
throw
new
InvalidOperationException
(
"Query results must be consumed in the correct order, and each result can only be consumed once"
);
var
typedIdentity
=
identity
.
ForGrid
(
type
,
gridIndex
);
CacheInfo
cache
=
GetCacheInfo
(
typedIdentity
,
null
,
true
);
var
deserializer
=
cache
.
Deserializer
;
int
hash
=
GetColumnHash
(
reader
);
if
(
deserializer
.
Func
==
null
||
deserializer
.
Hash
!=
hash
)
{
deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
type
,
reader
,
0
,
-
1
,
false
));
cache
.
Deserializer
=
deserializer
;
}
consumed
=
true
;
if
(
buffered
&&
this
.
reader
is
DbDataReader
)
{
return
ReadBufferedAsync
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
}
else
{
var
result
=
ReadDeferred
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
if
(
buffered
)
result
=
result
.
ToList
();
// for the "not a DbDataReader" scenario
return
Task
.
FromResult
(
result
);
}
}
private
async
Task
<
IEnumerable
<
T
>>
ReadBufferedAsync
<
T
>(
int
index
,
Func
<
IDataReader
,
object
>
deserializer
,
Identity
typedIdentity
)
{
try
{
var
reader
=
(
DbDataReader
)
this
.
reader
;
List
<
T
>
buffer
=
new
List
<
T
>();
while
(
index
==
gridIndex
&&
await
reader
.
ReadAsync
(
cancel
).
ConfigureAwait
(
false
))
{
buffer
.
Add
((
T
)
deserializer
(
reader
));
}
return
buffer
;
}
finally
// finally so that First etc progresses things even when multiple rows
{
if
(
index
==
gridIndex
)
{
await
NextResultAsync
().
ConfigureAwait
(
false
);
}
}
}
}
/// <summary>
/// <summary>
/// Execute a command that returns multiple result sets, and access each in turn
/// Execute a command that returns multiple result sets, and access each in turn
/// </summary>
/// </summary>
...
@@ -453,11 +592,11 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
...
@@ -453,11 +592,11 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
try
try
{
{
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
);
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
);
reader
=
await
cmd
.
ExecuteReaderAsync
(
wasClosed
?
CommandBehavior
.
CloseConnection
:
CommandBehavior
.
Default
,
command
.
CancellationToken
).
ConfigureAwait
(
false
);
reader
=
await
cmd
.
ExecuteReaderAsync
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
,
command
.
CancellationToken
).
ConfigureAwait
(
false
);
var
result
=
new
GridReader
(
cmd
,
reader
,
identity
);
var
result
=
new
GridReader
(
cmd
,
reader
,
identity
,
command
.
CancellationToken
);
wasClosed
=
false
;
// *if* the connection was closed and we got this far, then we now have a reader
wasClosed
=
false
;
// *if* the connection was closed and we got this far, then we now have a reader
// with the CloseConnection flag, so the reader will deal with the connection; we
// with the CloseConnection flag, so the reader will deal with the connection; we
// still need something in the "finally" to ensure that broken SQL still results
// still need something in the "finally" to ensure that broken SQL still results
...
@@ -535,8 +674,8 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
...
@@ -535,8 +674,8 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
try
try
{
{
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
paramReader
);
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
paramReader
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
wasClosed
?
CommandBehavior
.
CloseConnection
:
CommandBehavior
.
Default
,
command
.
CancellationToken
).
ConfigureAwait
(
false
);
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
wasClosed
?
CommandBehavior
.
CloseConnection
|
CommandBehavior
.
SequentialAccess
:
CommandBehavior
.
SequentialAccess
,
command
.
CancellationToken
).
ConfigureAwait
(
false
);
wasClosed
=
false
;
wasClosed
=
false
;
return
reader
;
return
reader
;
}
}
...
@@ -613,7 +752,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman
...
@@ -613,7 +752,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman
try
try
{
{
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
paramReader
);
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
paramReader
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
result
=
await
cmd
.
ExecuteScalarAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
result
=
await
cmd
.
ExecuteScalarAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
}
}
finally
finally
...
...
Dapper.Contrib.Tests/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -31,5 +31,5 @@
...
@@ -31,5 +31,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
Dapper.Contrib/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -31,5 +31,5 @@
...
@@ -31,5 +31,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
Dapper.SqlBuilder/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -31,5 +31,5 @@
...
@@ -31,5 +31,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
DapperTests NET35/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -31,5 +31,5 @@
...
@@ -31,5 +31,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
DapperTests NET45/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -31,5 +31,5 @@
...
@@ -31,5 +31,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
DapperTests NET45/Tests.cs
View file @
d0f880d1
...
@@ -4,6 +4,9 @@
...
@@ -4,6 +4,9 @@
using
System.Data
;
using
System.Data
;
using
System.Diagnostics
;
using
System.Diagnostics
;
using
System
;
using
System
;
using
System.Threading.Tasks
;
using
System.Threading
;
using
System.Data.SqlClient
;
namespace
DapperTests_NET45
namespace
DapperTests_NET45
{
{
...
@@ -18,6 +21,35 @@ public void TestBasicStringUsageAsync()
...
@@ -18,6 +21,35 @@ public void TestBasicStringUsageAsync()
arr
.
IsSequenceEqualTo
(
new
[]
{
"abc"
,
"def"
});
arr
.
IsSequenceEqualTo
(
new
[]
{
"abc"
,
"def"
});
}
}
}
}
public
void
TestBasicStringUsageAsyncNonBuffered
()
{
using
(
var
connection
=
Program
.
GetOpenConnection
())
{
var
query
=
connection
.
QueryAsync
<
string
>(
new
CommandDefinition
(
"select 'abc' as [Value] union all select @txt"
,
new
{
txt
=
"def"
},
flags
:
CommandFlags
.
None
));
var
arr
=
query
.
Result
.
ToArray
();
arr
.
IsSequenceEqualTo
(
new
[]
{
"abc"
,
"def"
});
}
}
public
void
TestLongOperationWithCancellation
()
{
using
(
var
connection
=
Program
.
GetClosedConnection
())
{
CancellationTokenSource
cancel
=
new
CancellationTokenSource
(
TimeSpan
.
FromSeconds
(
5
));
var
task
=
connection
.
QueryAsync
<
int
>(
new
CommandDefinition
(
"waitfor delay '00:00:10';select 1"
,
cancellationToken
:
cancel
.
Token
));
try
{
if
(!
task
.
Wait
(
TimeSpan
.
FromSeconds
(
7
)))
{
throw
new
TimeoutException
();
// should have cancelled
}
}
catch
(
AggregateException
agg
)
{
(
agg
.
InnerException
is
SqlException
).
IsTrue
();
}
}
}
public
void
TestBasicStringUsageClosedAsync
()
public
void
TestBasicStringUsageClosedAsync
()
{
{
...
@@ -29,6 +61,16 @@ public void TestBasicStringUsageClosedAsync()
...
@@ -29,6 +61,16 @@ public void TestBasicStringUsageClosedAsync()
}
}
}
}
public
void
TestQueryDynamicAsync
()
{
using
(
var
connection
=
Program
.
GetClosedConnection
())
{
var
row
=
connection
.
QueryAsync
(
"select 'abc' as [Value]"
).
Result
.
Single
();
string
value
=
row
.
Value
;
value
.
IsEqualTo
(
"abc"
);
}
}
public
void
TestClassWithStringUsageAsync
()
public
void
TestClassWithStringUsageAsync
()
{
{
using
(
var
connection
=
Program
.
GetOpenConnection
())
using
(
var
connection
=
Program
.
GetOpenConnection
())
...
@@ -104,8 +146,8 @@ public void TestMultiAsync()
...
@@ -104,8 +146,8 @@ public void TestMultiAsync()
{
{
using
(
Dapper
.
SqlMapper
.
GridReader
multi
=
conn
.
QueryMultipleAsync
(
"select 1; select 2"
).
Result
)
using
(
Dapper
.
SqlMapper
.
GridReader
multi
=
conn
.
QueryMultipleAsync
(
"select 1; select 2"
).
Result
)
{
{
multi
.
Read
<
int
>()
.
Single
().
IsEqualTo
(
1
);
multi
.
Read
Async
<
int
>().
Result
.
Single
().
IsEqualTo
(
1
);
multi
.
Read
<
int
>()
.
Single
().
IsEqualTo
(
2
);
multi
.
Read
Async
<
int
>().
Result
.
Single
().
IsEqualTo
(
2
);
}
}
}
}
}
}
...
@@ -115,8 +157,8 @@ public void TestMultiClosedConnAsync()
...
@@ -115,8 +157,8 @@ public void TestMultiClosedConnAsync()
{
{
using
(
Dapper
.
SqlMapper
.
GridReader
multi
=
conn
.
QueryMultipleAsync
(
"select 1; select 2"
).
Result
)
using
(
Dapper
.
SqlMapper
.
GridReader
multi
=
conn
.
QueryMultipleAsync
(
"select 1; select 2"
).
Result
)
{
{
multi
.
Read
<
int
>()
.
Single
().
IsEqualTo
(
1
);
multi
.
Read
Async
<
int
>().
Result
.
Single
().
IsEqualTo
(
1
);
multi
.
Read
<
int
>()
.
Single
().
IsEqualTo
(
2
);
multi
.
Read
Async
<
int
>().
Result
.
Single
().
IsEqualTo
(
2
);
}
}
}
}
}
}
...
...
Tests/Properties/AssemblyInfo.cs
View file @
d0f880d1
...
@@ -31,5 +31,5 @@
...
@@ -31,5 +31,5 @@
//
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// by using the '*' as shown below:
[
assembly
:
AssemblyVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyVersion
(
"1.
30
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
29
.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.
30
.0.0"
)]
dapper.nuspec
View file @
d0f880d1
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
<package
xmlns=
"http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"
>
<package
xmlns=
"http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"
>
<metadata
schemaVersion=
"2"
>
<metadata
schemaVersion=
"2"
>
<id>
Dapper
</id>
<id>
Dapper
</id>
<version>
1.
29
</version>
<version>
1.
30
</version>
<title>
Dapper dot net
</title>
<title>
Dapper dot net
</title>
<authors>
Sam Saffron,Marc Gravell
</authors>
<authors>
Sam Saffron,Marc Gravell
</authors>
<owners>
Sam Saffron,Marc Gravell
</owners>
<owners>
Sam Saffron,Marc Gravell
</owners>
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
<frameworkAssembly
assemblyName=
"Microsoft.CSharp"
targetFramework=
".NETFramework4.0-Client, .NETFramework4.0"
/>
<frameworkAssembly
assemblyName=
"Microsoft.CSharp"
targetFramework=
".NETFramework4.0-Client, .NETFramework4.0"
/>
</frameworkAssemblies>
</frameworkAssemblies>
<releaseNotes>
<releaseNotes>
* 1.30 - Better async cancellation
* 1.29 - Make underscore name matching optional (opt-in) - this can be a breaking change for some people
* 1.29 - Make underscore name matching optional (opt-in) - this can be a breaking change for some people
* 1.28 - Much better numeric type conversion; fix for large oracle strings; map Foo_Bar to FooBar (etc); ExecuteScalar added; stability fixes
* 1.28 - Much better numeric type conversion; fix for large oracle strings; map Foo_Bar to FooBar (etc); ExecuteScalar added; stability fixes
* 1.27 - Fixes for type-handler parse; ensure type-handlers get last dibs on configuring parameters
* 1.27 - Fixes for type-handler parse; ensure type-handlers get last dibs on configuring parameters
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment