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
8f31bdc2
Commit
8f31bdc2
authored
Aug 05, 2014
by
Marc Gravell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added ExecuteScalar (issue 22), and optional plan caching
parent
b07897d1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
223 additions
and
13 deletions
+223
-13
SqlMapper.cs
Dapper NET40/SqlMapper.cs
+99
-10
SqlMapperAsync.cs
Dapper NET45/SqlMapperAsync.cs
+80
-3
Tests.cs
DapperTests NET45/Tests.cs
+21
-0
Tests.cs
Tests/Tests.cs
+23
-0
No files found.
Dapper NET40/SqlMapper.cs
View file @
8f31bdc2
...
...
@@ -1010,6 +1010,58 @@ public static int Execute(this IDbConnection cnn, CommandDefinition command)
{
return
ExecuteImpl
(
cnn
,
ref
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
object
ExecuteScalar
(
#if CSHARP30
this
IDbConnection
cnn
,
string
sql
,
object
param
,
IDbTransaction
transaction
,
int
?
commandTimeout
,
CommandType
?
commandType
#else
this
IDbConnection
cnn
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
#endif
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
return
ExecuteScalarImpl
<
object
>(
cnn
,
ref
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
T
ExecuteScalar
<
T
>(
#if CSHARP30
this
IDbConnection
cnn
,
string
sql
,
object
param
,
IDbTransaction
transaction
,
int
?
commandTimeout
,
CommandType
?
commandType
#else
this
IDbConnection
cnn
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
#endif
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
return
ExecuteScalarImpl
<
T
>(
cnn
,
ref
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
object
ExecuteScalar
(
this
IDbConnection
cnn
,
CommandDefinition
command
)
{
return
ExecuteScalarImpl
<
object
>(
cnn
,
ref
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
T
ExecuteScalar
<
T
>(
this
IDbConnection
cnn
,
CommandDefinition
command
)
{
return
ExecuteScalarImpl
<
T
>(
cnn
,
ref
command
);
}
private
static
int
ExecuteImpl
(
this
IDbConnection
cnn
,
ref
CommandDefinition
command
)
{
object
param
=
command
.
Parameters
;
...
...
@@ -1068,12 +1120,6 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
return
ExecuteCommand
(
cnn
,
ref
command
,
param
==
null
?
null
:
info
.
ParamReader
);
}
private
static
CacheInfo
GetCacheInfo
(
Identity
identity
,
object
obj
,
object
addToCache
)
{
throw
new
NotImplementedException
();
}
/// <summary>
/// Execute parameterized SQL and return an <see cref="IDataReader"/>
/// </summary>
...
...
@@ -1304,7 +1350,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
if
(
tuple
.
Func
==
null
||
tuple
.
Hash
!=
hash
)
{
tuple
=
info
.
Deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
effectiveType
,
reader
,
0
,
-
1
,
false
));
SetQueryCache
(
identity
,
info
);
if
(
command
.
AddToCache
)
SetQueryCache
(
identity
,
info
);
}
var
func
=
tuple
.
Func
;
...
...
@@ -1318,7 +1364,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
}
else
if
(
val
==
null
||
val
is
T
)
{
yield
return
(
T
)
val
;
}
else
{
yield
return
(
T
)
Convert
.
ChangeType
(
val
,
effectiveType
);
yield
return
(
T
)
Convert
.
ChangeType
(
val
,
effectiveType
,
CultureInfo
.
InvariantCulture
);
}
}
// happy path; close the reader cleanly - no
...
...
@@ -1541,7 +1587,7 @@ partial class DontMap { }
var
deserializers
=
GenerateDeserializers
(
new
Type
[]
{
typeof
(
TFirst
),
typeof
(
TSecond
),
typeof
(
TThird
),
typeof
(
TFourth
),
typeof
(
TFifth
),
typeof
(
TSixth
),
typeof
(
TSeventh
)
},
splitOn
,
reader
);
deserializer
=
cinfo
.
Deserializer
=
new
DeserializerState
(
hash
,
deserializers
[
0
]);
otherDeserializers
=
cinfo
.
OtherDeserializers
=
deserializers
.
Skip
(
1
).
ToArray
();
SetQueryCache
(
identity
,
cinfo
);
if
(
command
.
AddToCache
)
SetQueryCache
(
identity
,
cinfo
);
}
Func
<
IDataReader
,
TReturn
>
mapIt
=
GenerateMapper
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
deserializer
.
Func
,
otherDeserializers
,
map
);
...
...
@@ -1764,7 +1810,6 @@ private static CacheInfo GetCacheInfo(Identity identity, object exampleParameter
return
GetTypeDeserializer
(
type
,
reader
,
startBound
,
length
,
returnNullIfFirstMissing
);
}
return
GetStructDeserializer
(
type
,
underlyingType
??
type
,
startBound
);
}
static
Func
<
IDataReader
,
object
>
GetHandlerDeserializer
(
ITypeHandler
handler
,
Type
type
,
int
startBound
)
{
...
...
@@ -2854,6 +2899,33 @@ private static int ExecuteCommand(IDbConnection cnn, ref CommandDefinition comma
}
}
private
static
T
ExecuteScalarImpl
<
T
>(
IDbConnection
cnn
,
ref
CommandDefinition
command
)
{
Action
<
IDbCommand
,
object
>
paramReader
=
null
;
object
param
=
command
.
Parameters
;
if
(
param
!=
null
)
{
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
null
,
param
.
GetType
(),
null
);
paramReader
=
GetCacheInfo
(
identity
,
command
.
Parameters
,
command
.
AddToCache
).
ParamReader
;
}
IDbCommand
cmd
=
null
;
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
object
result
;
try
{
cmd
=
command
.
SetupCommand
(
cnn
,
paramReader
);
if
(
wasClosed
)
cnn
.
Open
();
result
=
cmd
.
ExecuteScalar
();
}
finally
{
if
(
wasClosed
)
cnn
.
Close
();
if
(
cmd
!=
null
)
cmd
.
Dispose
();
}
return
Parse
<
T
>(
result
);
}
private
static
IDataReader
ExecuteReaderImpl
(
IDbConnection
cnn
,
ref
CommandDefinition
command
)
{
Action
<
IDbCommand
,
object
>
paramReader
=
GetParameterReader
(
cnn
,
ref
command
);
...
...
@@ -2938,6 +3010,23 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin
};
}
private
static
T
Parse
<
T
>(
object
value
)
{
if
(
value
==
null
||
value
is
DBNull
)
return
default
(
T
);
if
(
value
is
T
)
return
(
T
)
value
;
var
type
=
typeof
(
T
);
if
(
type
.
IsEnum
)
{
return
(
T
)
Enum
.
ToObject
(
type
,
value
);
}
ITypeHandler
handler
;
if
(
typeHandlers
.
TryGetValue
(
type
,
out
handler
))
{
return
(
T
)
handler
.
Parse
(
type
,
value
);
}
return
(
T
)
Convert
.
ChangeType
(
value
,
type
,
CultureInfo
.
InvariantCulture
);
}
static
readonly
MethodInfo
enumParse
=
typeof
(
Enum
).
GetMethod
(
"Parse"
,
new
Type
[]
{
typeof
(
Type
),
typeof
(
string
),
typeof
(
bool
)
}),
getItem
=
typeof
(
IDataRecord
).
GetProperties
(
BindingFlags
.
Instance
|
BindingFlags
.
Public
)
...
...
Dapper NET45/SqlMapperAsync.cs
View file @
8f31bdc2
...
...
@@ -59,7 +59,7 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
using
(
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
))
{
return
ExecuteReader
<
T
>(
reader
,
effectiveType
,
identity
,
info
).
ToList
();
return
ExecuteReader
<
T
>(
reader
,
effectiveType
,
identity
,
info
,
command
.
AddToCache
).
ToList
();
}
}
finally
...
...
@@ -407,14 +407,14 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
}
}
private
static
IEnumerable
<
T
>
ExecuteReader
<
T
>(
IDataReader
reader
,
Type
effectiveType
,
Identity
identity
,
CacheInfo
info
)
private
static
IEnumerable
<
T
>
ExecuteReader
<
T
>(
IDataReader
reader
,
Type
effectiveType
,
Identity
identity
,
CacheInfo
info
,
bool
addToCache
)
{
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
));
SetQueryCache
(
identity
,
info
);
if
(
addToCache
)
SetQueryCache
(
identity
,
info
);
}
var
func
=
tuple
.
Func
;
...
...
@@ -546,5 +546,82 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
if
(
cmd
!=
null
)
cmd
.
Dispose
();
}
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
Task
<
object
>
ExecuteScalarAsync
(
#if CSHARP30
this
IDbConnection
cnn
,
string
sql
,
object
param
,
IDbTransaction
transaction
,
int
?
commandTimeout
,
CommandType
?
commandType
#else
this
IDbConnection
cnn
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
#endif
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
return
ExecuteScalarImplAsync
<
object
>(
cnn
,
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
Task
<
T
>
ExecuteScalarAsync
<
T
>(
#if CSHARP30
this
IDbConnection
cnn
,
string
sql
,
object
param
,
IDbTransaction
transaction
,
int
?
commandTimeout
,
CommandType
?
commandType
#else
this
IDbConnection
cnn
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
#endif
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
);
return
ExecuteScalarImplAsync
<
T
>(
cnn
,
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
Task
<
object
>
ExecuteScalarAsync
(
this
IDbConnection
cnn
,
CommandDefinition
command
)
{
return
ExecuteScalarImplAsync
<
object
>(
cnn
,
command
);
}
/// <summary>
/// Execute parameterized SQL that selects a single value
/// </summary>
/// <returns>The first cell selected</returns>
public
static
Task
<
T
>
ExecuteScalarAsync
<
T
>(
this
IDbConnection
cnn
,
CommandDefinition
command
)
{
return
ExecuteScalarImplAsync
<
T
>(
cnn
,
command
);
}
private
async
static
Task
<
T
>
ExecuteScalarImplAsync
<
T
>(
IDbConnection
cnn
,
CommandDefinition
command
)
{
Action
<
IDbCommand
,
object
>
paramReader
=
null
;
object
param
=
command
.
Parameters
;
if
(
param
!=
null
)
{
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
null
,
param
.
GetType
(),
null
);
paramReader
=
GetCacheInfo
(
identity
,
command
.
Parameters
,
command
.
AddToCache
).
ParamReader
;
}
DbCommand
cmd
=
null
;
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
object
result
;
try
{
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
paramReader
);
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
result
=
await
cmd
.
ExecuteScalarAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
);
}
finally
{
if
(
wasClosed
)
cnn
.
Close
();
if
(
cmd
!=
null
)
cmd
.
Dispose
();
}
return
Parse
<
T
>(
result
);
}
}
}
\ No newline at end of file
DapperTests NET45/Tests.cs
View file @
8f31bdc2
...
...
@@ -292,5 +292,26 @@ public class SomeType
public
int
A
{
get
;
set
;
}
public
string
B
{
get
;
set
;
}
}
public
void
Issue22_ExecuteScalar
()
{
using
(
var
connection
=
Program
.
GetOpenConnection
())
{
int
i
=
connection
.
ExecuteScalarAsync
<
int
>(
"select 123"
).
Result
;
i
.
IsEqualTo
(
123
);
i
=
connection
.
ExecuteScalarAsync
<
int
>(
"select cast(123 as bigint)"
).
Result
;
i
.
IsEqualTo
(
123
);
long
j
=
connection
.
ExecuteScalarAsync
<
long
>(
"select 123"
).
Result
;
j
.
IsEqualTo
(
123L
);
j
=
connection
.
ExecuteScalarAsync
<
long
>(
"select cast(123 as bigint)"
).
Result
;
j
.
IsEqualTo
(
123L
);
int
?
k
=
connection
.
ExecuteScalar
<
int
?>(
"select @i"
,
new
{
i
=
default
(
int
?)
});
k
.
IsNull
();
}
}
}
}
\ No newline at end of file
Tests/Tests.cs
View file @
8f31bdc2
...
...
@@ -3161,6 +3161,29 @@ public void Issue130_IConvertible()
b
.
IsEqualTo
(
"4"
);
}
public
void
Issue22_ExecuteScalar
()
{
int
i
=
connection
.
ExecuteScalar
<
int
>(
"select 123"
);
i
.
IsEqualTo
(
123
);
i
=
connection
.
ExecuteScalar
<
int
>(
"select cast(123 as bigint)"
);
i
.
IsEqualTo
(
123
);
long
j
=
connection
.
ExecuteScalar
<
long
>(
"select 123"
);
j
.
IsEqualTo
(
123L
);
j
=
connection
.
ExecuteScalar
<
long
>(
"select cast(123 as bigint)"
);
j
.
IsEqualTo
(
123L
);
int
?
k
=
connection
.
ExecuteScalar
<
int
?>(
"select @i"
,
new
{
i
=
default
(
int
?)
});
k
.
IsNull
();
Dapper
.
EntityFramework
.
Handlers
.
Register
();
var
geo
=
DbGeography
.
LineFromText
(
"LINESTRING(-122.360 47.656, -122.343 47.656 )"
,
4326
);
var
geo2
=
connection
.
ExecuteScalar
<
DbGeography
>(
"select @geo"
,
new
{
geo
});
geo2
.
IsNotNull
();
}
#if POSTGRESQL
class
Cat
...
...
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