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
12886d80
Commit
12886d80
authored
Nov 11, 2015
by
Nick Craver
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #391 from henkmollema/code-cleanup2
Code cleanup - take 2
parents
295d1ad2
c28a87ff
Changes
21
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
275 additions
and
377 deletions
+275
-377
CommandDefinition.cs
Dapper/CommandDefinition.cs
+48
-52
CustomPropertyTypeMap.cs
Dapper/CustomPropertyTypeMap.cs
+2
-2
DataTableHandler.cs
Dapper/DataTableHandler.cs
+1
-1
DbString.cs
Dapper/DbString.cs
+1
-1
DefaultTypeMap.cs
Dapper/DefaultTypeMap.cs
+3
-10
DynamicParameters.cs
Dapper/DynamicParameters.cs
+17
-20
FeatureSupport.cs
Dapper/FeatureSupport.cs
+2
-2
SimpleMemberMap.cs
Dapper/SimpleMemberMap.cs
+17
-49
SqlDataRecordHandler.cs
Dapper/SqlDataRecordHandler.cs
+1
-1
SqlDataRecordListTVPParameter.cs
Dapper/SqlDataRecordListTVPParameter.cs
+1
-1
SqlMapper.Async.cs
Dapper/SqlMapper.Async.cs
+18
-19
SqlMapper.DapperRow.cs
Dapper/SqlMapper.DapperRow.cs
+5
-9
SqlMapper.DataTable.cs
Dapper/SqlMapper.DataTable.cs
+4
-4
SqlMapper.GridReader.Async.cs
Dapper/SqlMapper.GridReader.Async.cs
+19
-23
SqlMapper.GridReader.cs
Dapper/SqlMapper.GridReader.cs
+15
-33
SqlMapper.Identity.cs
Dapper/SqlMapper.Identity.cs
+13
-13
SqlMapper.Link.cs
Dapper/SqlMapper.Link.cs
+3
-3
SqlMapper.LiteralToken.cs
Dapper/SqlMapper.LiteralToken.cs
+5
-5
SqlMapper.cs
Dapper/SqlMapper.cs
+87
-98
TableValuedParameter.cs
Dapper/TableValuedParameter.cs
+3
-3
WrappedReader.cs
Dapper/WrappedReader.cs
+10
-28
No files found.
Dapper/CommandDefinition.cs
View file @
12886d80
...
@@ -18,7 +18,8 @@
...
@@ -18,7 +18,8 @@
#endif
#endif
namespace
Dapper
namespace
Dapper
{
/// <summary>
{
/// <summary>
/// Represents the key aspects of a sql operation
/// Represents the key aspects of a sql operation
/// </summary>
/// </summary>
public
struct
CommandDefinition
public
struct
CommandDefinition
...
@@ -34,61 +35,56 @@ internal static CommandDefinition ForCallback(object parameters)
...
@@ -34,61 +35,56 @@ internal static CommandDefinition ForCallback(object parameters)
return
default
(
CommandDefinition
);
return
default
(
CommandDefinition
);
}
}
}
}
private
readonly
string
commandText
;
private
readonly
object
parameters
;
private
readonly
IDbTransaction
transaction
;
private
readonly
int
?
commandTimeout
;
private
readonly
CommandType
?
commandType
;
private
readonly
CommandFlags
flags
;
internal
void
OnCompleted
()
internal
void
OnCompleted
()
{
{
if
(
parameters
is
SqlMapper
.
IParameterCallbacks
)
(
Parameters
as
SqlMapper
.
IParameterCallbacks
)?.
OnCompleted
();
{
((
SqlMapper
.
IParameterCallbacks
)
parameters
).
OnCompleted
();
}
}
}
/// <summary>
/// <summary>
/// The command (sql or a stored-procedure name) to execute
/// The command (sql or a stored-procedure name) to execute
/// </summary>
/// </summary>
public
string
CommandText
{
get
{
return
commandText
;
}
}
public
string
CommandText
{
get
;
}
/// <summary>
/// <summary>
/// The parameters associated with the command
/// The parameters associated with the command
/// </summary>
/// </summary>
public
object
Parameters
{
get
{
return
parameters
;
}
}
public
object
Parameters
{
get
;
}
/// <summary>
/// <summary>
/// The active transaction for the command
/// The active transaction for the command
/// </summary>
/// </summary>
public
IDbTransaction
Transaction
{
get
{
return
transaction
;
}
}
public
IDbTransaction
Transaction
{
get
;
}
/// <summary>
/// <summary>
/// The effective timeout for the command
/// The effective timeout for the command
/// </summary>
/// </summary>
public
int
?
CommandTimeout
{
get
{
return
commandTimeout
;
}
}
public
int
?
CommandTimeout
{
get
;
}
/// <summary>
/// <summary>
/// The type of command that the command-text represents
/// The type of command that the command-text represents
/// </summary>
/// </summary>
public
CommandType
?
CommandType
{
get
{
return
commandType
;
}
}
public
CommandType
?
CommandType
{
get
;
}
/// <summary>
/// <summary>
/// Should data be buffered before returning?
/// Should data be buffered before returning?
/// </summary>
/// </summary>
public
bool
Buffered
{
get
{
return
(
flags
&
CommandFlags
.
Buffered
)
!=
0
;
}
}
public
bool
Buffered
=>
(
Flags
&
CommandFlags
.
Buffered
)
!=
0
;
/// <summary>
/// <summary>
/// Should the plan for this query be cached?
/// Should the plan for this query be cached?
/// </summary>
/// </summary>
internal
bool
AddToCache
{
get
{
return
(
flags
&
CommandFlags
.
NoCache
)
==
0
;
}
}
internal
bool
AddToCache
=>
(
Flags
&
CommandFlags
.
NoCache
)
==
0
;
/// <summary>
/// <summary>
/// Additional state flags against this command
/// Additional state flags against this command
/// </summary>
/// </summary>
public
CommandFlags
Flags
{
get
{
return
flags
;
}
}
public
CommandFlags
Flags
{
get
;
}
/// <summary>
/// <summary>
/// Can async queries be pipelined?
/// Can async queries be pipelined?
/// </summary>
/// </summary>
public
bool
Pipelined
{
get
{
return
(
flags
&
CommandFlags
.
Pipelined
)
!=
0
;
}
}
public
bool
Pipelined
=>
(
Flags
&
CommandFlags
.
Pipelined
)
!=
0
;
/// <summary>
/// <summary>
/// Initialize the command definition
/// Initialize the command definition
...
@@ -100,59 +96,58 @@ internal void OnCompleted()
...
@@ -100,59 +96,58 @@ internal void OnCompleted()
#endif
#endif
)
)
{
{
this
.
c
ommandText
=
commandText
;
C
ommandText
=
commandText
;
this
.
p
arameters
=
parameters
;
P
arameters
=
parameters
;
this
.
t
ransaction
=
transaction
;
T
ransaction
=
transaction
;
this
.
c
ommandTimeout
=
commandTimeout
;
C
ommandTimeout
=
commandTimeout
;
this
.
c
ommandType
=
commandType
;
C
ommandType
=
commandType
;
this
.
f
lags
=
flags
;
F
lags
=
flags
;
#if ASYNC
#if ASYNC
this
.
c
ancellationToken
=
cancellationToken
;
C
ancellationToken
=
cancellationToken
;
#endif
#endif
}
}
private
CommandDefinition
(
object
parameters
)
:
this
()
private
CommandDefinition
(
object
parameters
)
:
this
()
{
{
this
.
p
arameters
=
parameters
;
P
arameters
=
parameters
;
}
}
#if ASYNC
#if ASYNC
private
readonly
CancellationToken
cancellationToken
;
/// <summary>
/// <summary>
/// For asynchronous operations, the cancellation-token
/// For asynchronous operations, the cancellation-token
/// </summary>
/// </summary>
public
CancellationToken
CancellationToken
{
get
{
return
cancellationToken
;
}
}
public
CancellationToken
CancellationToken
{
get
;
}
#endif
#endif
internal
IDbCommand
SetupCommand
(
IDbConnection
cnn
,
Action
<
IDbCommand
,
object
>
paramReader
)
internal
IDbCommand
SetupCommand
(
IDbConnection
cnn
,
Action
<
IDbCommand
,
object
>
paramReader
)
{
{
var
cmd
=
cnn
.
CreateCommand
();
var
cmd
=
cnn
.
CreateCommand
();
var
init
=
GetInit
(
cmd
.
GetType
());
var
init
=
GetInit
(
cmd
.
GetType
());
i
f
(
init
!=
null
)
init
(
cmd
);
i
nit
?.
Invoke
(
cmd
);
if
(
t
ransaction
!=
null
)
if
(
T
ransaction
!=
null
)
cmd
.
Transaction
=
t
ransaction
;
cmd
.
Transaction
=
T
ransaction
;
cmd
.
CommandText
=
c
ommandText
;
cmd
.
CommandText
=
C
ommandText
;
if
(
c
ommandTimeout
.
HasValue
)
if
(
C
ommandTimeout
.
HasValue
)
{
{
cmd
.
CommandTimeout
=
c
ommandTimeout
.
Value
;
cmd
.
CommandTimeout
=
C
ommandTimeout
.
Value
;
}
}
else
if
(
SqlMapper
.
Settings
.
CommandTimeout
.
HasValue
)
else
if
(
SqlMapper
.
Settings
.
CommandTimeout
.
HasValue
)
{
{
cmd
.
CommandTimeout
=
SqlMapper
.
Settings
.
CommandTimeout
.
Value
;
cmd
.
CommandTimeout
=
SqlMapper
.
Settings
.
CommandTimeout
.
Value
;
}
}
if
(
commandType
.
HasValue
)
if
(
CommandType
.
HasValue
)
cmd
.
CommandType
=
commandType
.
Value
;
cmd
.
CommandType
=
CommandType
.
Value
;
if
(
paramReader
!=
null
)
paramReader
?.
Invoke
(
cmd
,
Parameters
);
{
paramReader
(
cmd
,
parameters
);
}
return
cmd
;
return
cmd
;
}
}
static
SqlMapper
.
Link
<
Type
,
Action
<
IDbCommand
>>
commandInitCache
;
private
static
SqlMapper
.
Link
<
Type
,
Action
<
IDbCommand
>>
commandInitCache
;
static
Action
<
IDbCommand
>
GetInit
(
Type
commandType
)
private
static
Action
<
IDbCommand
>
GetInit
(
Type
commandType
)
{
{
if
(
commandType
==
null
)
return
null
;
// GIGO
if
(
commandType
==
null
)
return
null
;
// GIGO
Action
<
IDbCommand
>
action
;
Action
<
IDbCommand
>
action
;
if
(
SqlMapper
.
Link
<
Type
,
Action
<
IDbCommand
>>.
TryGet
(
commandInitCache
,
commandType
,
out
action
))
if
(
SqlMapper
.
Link
<
Type
,
Action
<
IDbCommand
>>.
TryGet
(
commandInitCache
,
commandType
,
out
action
))
{
{
...
@@ -190,7 +185,8 @@ static Action<IDbCommand> GetInit(Type commandType)
...
@@ -190,7 +185,8 @@ static Action<IDbCommand> GetInit(Type commandType)
SqlMapper
.
Link
<
Type
,
Action
<
IDbCommand
>>.
TryAdd
(
ref
commandInitCache
,
commandType
,
ref
action
);
SqlMapper
.
Link
<
Type
,
Action
<
IDbCommand
>>.
TryAdd
(
ref
commandInitCache
,
commandType
,
ref
action
);
return
action
;
return
action
;
}
}
static
MethodInfo
GetBasicPropertySetter
(
Type
declaringType
,
string
name
,
Type
expectedType
)
private
static
MethodInfo
GetBasicPropertySetter
(
Type
declaringType
,
string
name
,
Type
expectedType
)
{
{
var
prop
=
declaringType
.
GetProperty
(
name
,
BindingFlags
.
Public
|
BindingFlags
.
Instance
);
var
prop
=
declaringType
.
GetProperty
(
name
,
BindingFlags
.
Public
|
BindingFlags
.
Instance
);
ParameterInfo
[]
indexers
;
ParameterInfo
[]
indexers
;
...
...
Dapper/CustomPropertyTypeMap.cs
View file @
12886d80
...
@@ -20,10 +20,10 @@ public sealed class CustomPropertyTypeMap : SqlMapper.ITypeMap
...
@@ -20,10 +20,10 @@ public sealed class CustomPropertyTypeMap : SqlMapper.ITypeMap
public
CustomPropertyTypeMap
(
Type
type
,
Func
<
Type
,
string
,
PropertyInfo
>
propertySelector
)
public
CustomPropertyTypeMap
(
Type
type
,
Func
<
Type
,
string
,
PropertyInfo
>
propertySelector
)
{
{
if
(
type
==
null
)
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
throw
new
ArgumentNullException
(
nameof
(
type
)
);
if
(
propertySelector
==
null
)
if
(
propertySelector
==
null
)
throw
new
ArgumentNullException
(
"propertySelector"
);
throw
new
ArgumentNullException
(
nameof
(
propertySelector
)
);
_type
=
type
;
_type
=
type
;
_propertySelector
=
propertySelector
;
_propertySelector
=
propertySelector
;
...
...
Dapper/DataTableHandler.cs
View file @
12886d80
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
#if !DNXCORE50
#if !DNXCORE50
namespace
Dapper
namespace
Dapper
{
{
sealed
class
DataTableHandler
:
Dapper
.
SqlMapper
.
ITypeHandler
sealed
class
DataTableHandler
:
SqlMapper
.
ITypeHandler
{
{
public
object
Parse
(
Type
destinationType
,
object
value
)
public
object
Parse
(
Type
destinationType
,
object
value
)
{
{
...
...
Dapper/DbString.cs
View file @
12886d80
...
@@ -19,7 +19,7 @@ namespace Dapper
...
@@ -19,7 +19,7 @@ namespace Dapper
/// <summary>
/// <summary>
/// This class represents a SQL string, it can be used if you need to denote your parameter is a Char vs VarChar vs nVarChar vs nChar
/// This class represents a SQL string, it can be used if you need to denote your parameter is a Char vs VarChar vs nVarChar vs nChar
/// </summary>
/// </summary>
public
sealed
class
DbString
:
Dapper
.
SqlMapper
.
ICustomQueryParameter
public
sealed
class
DbString
:
SqlMapper
.
ICustomQueryParameter
{
{
/// <summary>
/// <summary>
/// Default value for IsAnsi.
/// Default value for IsAnsi.
...
...
Dapper/DefaultTypeMap.cs
View file @
12886d80
...
@@ -11,7 +11,6 @@ namespace Dapper
...
@@ -11,7 +11,6 @@ namespace Dapper
sealed
class
DefaultTypeMap
:
SqlMapper
.
ITypeMap
sealed
class
DefaultTypeMap
:
SqlMapper
.
ITypeMap
{
{
private
readonly
List
<
FieldInfo
>
_fields
;
private
readonly
List
<
FieldInfo
>
_fields
;
private
readonly
List
<
PropertyInfo
>
_properties
;
private
readonly
Type
_type
;
private
readonly
Type
_type
;
/// <summary>
/// <summary>
...
@@ -21,10 +20,10 @@ sealed class DefaultTypeMap : SqlMapper.ITypeMap
...
@@ -21,10 +20,10 @@ sealed class DefaultTypeMap : SqlMapper.ITypeMap
public
DefaultTypeMap
(
Type
type
)
public
DefaultTypeMap
(
Type
type
)
{
{
if
(
type
==
null
)
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
throw
new
ArgumentNullException
(
nameof
(
type
)
);
_fields
=
GetSettableFields
(
type
);
_fields
=
GetSettableFields
(
type
);
_p
roperties
=
GetSettableProps
(
type
);
P
roperties
=
GetSettableProps
(
type
);
_type
=
type
;
_type
=
type
;
}
}
#if DNXCORE50
#if DNXCORE50
...
@@ -184,12 +183,6 @@ public SqlMapper.IMemberMap GetMember(string columnName)
...
@@ -184,12 +183,6 @@ public SqlMapper.IMemberMap GetMember(string columnName)
/// </summary>
/// </summary>
public
static
bool
MatchNamesWithUnderscores
{
get
;
set
;
}
public
static
bool
MatchNamesWithUnderscores
{
get
;
set
;
}
public
List
<
PropertyInfo
>
Properties
public
List
<
PropertyInfo
>
Properties
{
get
;
}
{
get
{
return
_properties
;
}
}
}
}
}
}
Dapper/DynamicParameters.cs
View file @
12886d80
...
@@ -246,7 +246,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
...
@@ -246,7 +246,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
{
((
SqlMapper
.
ICustomQueryParameter
)
val
).
AddParameter
(
command
,
name
);
((
SqlMapper
.
ICustomQueryParameter
)
val
).
AddParameter
(
command
,
name
);
}
}
else
if
(
dbType
==
DynamicParameters
.
EnumerableMultiParameter
)
else
if
(
dbType
==
EnumerableMultiParameter
)
{
{
#pragma warning disable 612, 618
#pragma warning disable 612, 618
SqlMapper
.
PackListParameters
(
command
,
name
,
val
);
SqlMapper
.
PackListParameters
(
command
,
name
,
val
);
...
@@ -276,13 +276,10 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
...
@@ -276,13 +276,10 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
p
.
DbType
=
dbType
.
Value
;
p
.
DbType
=
dbType
.
Value
;
}
}
var
s
=
val
as
string
;
var
s
=
val
as
string
;
if
(
s
!=
null
)
if
(
s
?.
Length
<=
DbString
.
DefaultLength
)
{
if
(
s
.
Length
<=
DbString
.
DefaultLength
)
{
{
p
.
Size
=
DbString
.
DefaultLength
;
p
.
Size
=
DbString
.
DefaultLength
;
}
}
}
if
(
param
.
Size
!=
null
)
p
.
Size
=
param
.
Size
.
Value
;
if
(
param
.
Size
!=
null
)
p
.
Size
=
param
.
Size
.
Value
;
if
(
param
.
Precision
!=
null
)
p
.
Precision
=
param
.
Precision
.
Value
;
if
(
param
.
Precision
!=
null
)
p
.
Precision
=
param
.
Precision
.
Value
;
if
(
param
.
Scale
!=
null
)
p
.
Scale
=
param
.
Scale
.
Value
;
if
(
param
.
Scale
!=
null
)
p
.
Scale
=
param
.
Scale
.
Value
;
...
@@ -385,11 +382,11 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
...
@@ -385,11 +382,11 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
{
{
// Insert the names in the right order so expression
// Insert the names in the right order so expression
// "Post.Author.Name" becomes parameter "PostAuthorName"
// "Post.Author.Name" becomes parameter "PostAuthorName"
names
.
Insert
(
0
,
diving
.
Member
.
Name
);
names
.
Insert
(
0
,
diving
?
.
Member
.
Name
);
chain
.
Insert
(
0
,
diving
);
chain
.
Insert
(
0
,
diving
);
var
constant
=
diving
.
Expression
as
ParameterExpression
;
var
constant
=
diving
?
.
Expression
as
ParameterExpression
;
diving
=
diving
.
Expression
as
MemberExpression
;
diving
=
diving
?
.
Expression
as
MemberExpression
;
if
(
constant
!=
null
&&
if
(
constant
!=
null
&&
constant
.
Type
==
typeof
(
T
))
constant
.
Type
==
typeof
(
T
))
...
@@ -423,7 +420,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
...
@@ -423,7 +420,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
if
(
setter
!=
null
)
goto
MAKECALLBACK
;
if
(
setter
!=
null
)
goto
MAKECALLBACK
;
// Come on let's build a method, let's build it, let's build it now!
// Come on let's build a method, let's build it, let's build it now!
var
dm
=
new
DynamicMethod
(
string
.
Format
(
"ExpressionParam{0}"
,
Guid
.
NewGuid
()),
null
,
new
[]
{
typeof
(
object
),
this
.
GetType
()
},
true
);
var
dm
=
new
DynamicMethod
(
$"ExpressionParam
{
Guid
.
NewGuid
()}
"
,
null
,
new
[]
{
typeof
(
object
),
GetType
()
},
true
);
var
il
=
dm
.
GetILGenerator
();
var
il
=
dm
.
GetILGenerator
();
il
.
Emit
(
OpCodes
.
Ldarg_0
);
// [object]
il
.
Emit
(
OpCodes
.
Ldarg_0
);
// [object]
...
@@ -446,7 +443,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
...
@@ -446,7 +443,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
}
}
}
}
var
paramGetter
=
this
.
GetType
().
GetMethod
(
"Get"
,
new
Type
[]
{
typeof
(
string
)
}).
MakeGenericMethod
(
lastMemberAccess
.
Type
);
var
paramGetter
=
GetType
().
GetMethod
(
"Get"
,
new
Type
[]
{
typeof
(
string
)
}).
MakeGenericMethod
(
lastMemberAccess
.
Type
);
il
.
Emit
(
OpCodes
.
Ldarg_1
);
// [target] [DynamicParameters]
il
.
Emit
(
OpCodes
.
Ldarg_1
);
// [target] [DynamicParameters]
il
.
Emit
(
OpCodes
.
Ldstr
,
dynamicParamName
);
// [target] [DynamicParameters] [ParamName]
il
.
Emit
(
OpCodes
.
Ldstr
,
dynamicParamName
);
// [target] [DynamicParameters] [ParamName]
...
@@ -478,10 +475,10 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
...
@@ -478,10 +475,10 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
{
{
// Finally, prep the parameter and attach the callback to it
// Finally, prep the parameter and attach the callback to it
ParamInfo
parameter
;
ParamInfo
parameter
;
var
targetMemberType
=
lastMemberAccess
.
Type
;
var
targetMemberType
=
lastMemberAccess
?
.
Type
;
int
sizeToSet
=
(!
size
.
HasValue
&&
targetMemberType
==
typeof
(
string
))
?
DbString
.
DefaultLength
:
size
??
0
;
int
sizeToSet
=
(!
size
.
HasValue
&&
targetMemberType
==
typeof
(
string
))
?
DbString
.
DefaultLength
:
size
??
0
;
if
(
this
.
parameters
.
TryGetValue
(
dynamicParamName
,
out
parameter
))
if
(
parameters
.
TryGetValue
(
dynamicParamName
,
out
parameter
))
{
{
parameter
.
ParameterDirection
=
parameter
.
AttachedParam
.
Direction
=
ParameterDirection
.
InputOutput
;
parameter
.
ParameterDirection
=
parameter
.
AttachedParam
.
Direction
=
ParameterDirection
.
InputOutput
;
...
@@ -493,14 +490,14 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
...
@@ -493,14 +490,14 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
else
else
{
{
SqlMapper
.
ITypeHandler
handler
;
SqlMapper
.
ITypeHandler
handler
;
dbType
=
(!
dbType
.
HasValue
)
?
SqlMapper
.
LookupDbType
(
targetMemberType
,
targetMemberType
.
Name
,
true
,
out
handler
)
:
dbType
;
dbType
=
(!
dbType
.
HasValue
)
?
SqlMapper
.
LookupDbType
(
targetMemberType
,
targetMemberType
?
.
Name
,
true
,
out
handler
)
:
dbType
;
// CameFromTemplate property would not apply here because this new param
// CameFromTemplate property would not apply here because this new param
// Still needs to be added to the command
// Still needs to be added to the command
this
.
Add
(
dynamicParamName
,
expression
.
Compile
().
Invoke
(
target
),
null
,
ParameterDirection
.
InputOutput
,
sizeToSet
);
Add
(
dynamicParamName
,
expression
.
Compile
().
Invoke
(
target
),
null
,
ParameterDirection
.
InputOutput
,
sizeToSet
);
}
}
parameter
=
this
.
parameters
[
dynamicParamName
];
parameter
=
parameters
[
dynamicParamName
];
parameter
.
OutputCallback
=
setter
;
parameter
.
OutputCallback
=
setter
;
parameter
.
OutputTarget
=
target
;
parameter
.
OutputTarget
=
target
;
});
});
...
@@ -518,7 +515,7 @@ void SqlMapper.IParameterCallbacks.OnCompleted()
...
@@ -518,7 +515,7 @@ void SqlMapper.IParameterCallbacks.OnCompleted()
{
{
foreach
(
var
param
in
(
from
p
in
parameters
select
p
.
Value
))
foreach
(
var
param
in
(
from
p
in
parameters
select
p
.
Value
))
{
{
if
(
param
.
OutputCallback
!=
null
)
param
.
OutputCallback
(
param
.
OutputTarget
,
this
);
param
.
OutputCallback
?.
Invoke
(
param
.
OutputTarget
,
this
);
}
}
}
}
}
}
...
...
Dapper/FeatureSupport.cs
View file @
12886d80
...
@@ -28,7 +28,7 @@ private static readonly FeatureSupport
...
@@ -28,7 +28,7 @@ private static readonly FeatureSupport
/// </summary>
/// </summary>
public
static
FeatureSupport
Get
(
IDbConnection
connection
)
public
static
FeatureSupport
Get
(
IDbConnection
connection
)
{
{
string
name
=
connection
==
null
?
null
:
connection
.
GetType
().
Name
;
string
name
=
connection
?
.
GetType
().
Name
;
if
(
string
.
Equals
(
name
,
"npgsqlconnection"
,
StringComparison
.
OrdinalIgnoreCase
))
return
postgres
;
if
(
string
.
Equals
(
name
,
"npgsqlconnection"
,
StringComparison
.
OrdinalIgnoreCase
))
return
postgres
;
return
@default
;
return
@default
;
}
}
...
@@ -39,7 +39,7 @@ private FeatureSupport(bool arrays)
...
@@ -39,7 +39,7 @@ private FeatureSupport(bool arrays)
/// <summary>
/// <summary>
/// True if the db supports array columns e.g. Postgresql
/// True if the db supports array columns e.g. Postgresql
/// </summary>
/// </summary>
public
bool
Arrays
{
get
;
private
set
;
}
public
bool
Arrays
{
get
;
}
}
}
}
}
Dapper/SimpleMemberMap.cs
View file @
12886d80
...
@@ -8,11 +8,6 @@ namespace Dapper
...
@@ -8,11 +8,6 @@ namespace Dapper
/// </summary>
/// </summary>
sealed
class
SimpleMemberMap
:
SqlMapper
.
IMemberMap
sealed
class
SimpleMemberMap
:
SqlMapper
.
IMemberMap
{
{
private
readonly
string
_columnName
;
private
readonly
PropertyInfo
_property
;
private
readonly
FieldInfo
_field
;
private
readonly
ParameterInfo
_parameter
;
/// <summary>
/// <summary>
/// Creates instance for simple property mapping
/// Creates instance for simple property mapping
/// </summary>
/// </summary>
...
@@ -21,13 +16,13 @@ sealed class SimpleMemberMap : SqlMapper.IMemberMap
...
@@ -21,13 +16,13 @@ sealed class SimpleMemberMap : SqlMapper.IMemberMap
public
SimpleMemberMap
(
string
columnName
,
PropertyInfo
property
)
public
SimpleMemberMap
(
string
columnName
,
PropertyInfo
property
)
{
{
if
(
columnName
==
null
)
if
(
columnName
==
null
)
throw
new
ArgumentNullException
(
"columnName"
);
throw
new
ArgumentNullException
(
nameof
(
columnName
)
);
if
(
property
==
null
)
if
(
property
==
null
)
throw
new
ArgumentNullException
(
"property"
);
throw
new
ArgumentNullException
(
nameof
(
property
)
);
_c
olumnName
=
columnName
;
C
olumnName
=
columnName
;
_p
roperty
=
property
;
P
roperty
=
property
;
}
}
/// <summary>
/// <summary>
...
@@ -38,13 +33,13 @@ public SimpleMemberMap(string columnName, PropertyInfo property)
...
@@ -38,13 +33,13 @@ public SimpleMemberMap(string columnName, PropertyInfo property)
public
SimpleMemberMap
(
string
columnName
,
FieldInfo
field
)
public
SimpleMemberMap
(
string
columnName
,
FieldInfo
field
)
{
{
if
(
columnName
==
null
)
if
(
columnName
==
null
)
throw
new
ArgumentNullException
(
"columnName"
);
throw
new
ArgumentNullException
(
nameof
(
columnName
)
);
if
(
field
==
null
)
if
(
field
==
null
)
throw
new
ArgumentNullException
(
"field"
);
throw
new
ArgumentNullException
(
nameof
(
field
)
);
_c
olumnName
=
columnName
;
C
olumnName
=
columnName
;
_f
ield
=
field
;
F
ield
=
field
;
}
}
/// <summary>
/// <summary>
...
@@ -55,66 +50,39 @@ public SimpleMemberMap(string columnName, FieldInfo field)
...
@@ -55,66 +50,39 @@ public SimpleMemberMap(string columnName, FieldInfo field)
public
SimpleMemberMap
(
string
columnName
,
ParameterInfo
parameter
)
public
SimpleMemberMap
(
string
columnName
,
ParameterInfo
parameter
)
{
{
if
(
columnName
==
null
)
if
(
columnName
==
null
)
throw
new
ArgumentNullException
(
"columnName"
);
throw
new
ArgumentNullException
(
nameof
(
columnName
)
);
if
(
parameter
==
null
)
if
(
parameter
==
null
)
throw
new
ArgumentNullException
(
"parameter"
);
throw
new
ArgumentNullException
(
nameof
(
parameter
)
);
_c
olumnName
=
columnName
;
C
olumnName
=
columnName
;
_p
arameter
=
parameter
;
P
arameter
=
parameter
;
}
}
/// <summary>
/// <summary>
/// DataReader column name
/// DataReader column name
/// </summary>
/// </summary>
public
string
ColumnName
public
string
ColumnName
{
get
;
}
{
get
{
return
_columnName
;
}
}
/// <summary>
/// <summary>
/// Target member type
/// Target member type
/// </summary>
/// </summary>
public
Type
MemberType
public
Type
MemberType
=>
Field
?.
FieldType
??
Property
?.
PropertyType
??
Parameter
?.
ParameterType
;
{
get
{
if
(
_field
!=
null
)
return
_field
.
FieldType
;
if
(
_property
!=
null
)
return
_property
.
PropertyType
;
if
(
_parameter
!=
null
)
return
_parameter
.
ParameterType
;
return
null
;
}
}
/// <summary>
/// <summary>
/// Target property
/// Target property
/// </summary>
/// </summary>
public
PropertyInfo
Property
public
PropertyInfo
Property
{
get
;
}
{
get
{
return
_property
;
}
}
/// <summary>
/// <summary>
/// Target field
/// Target field
/// </summary>
/// </summary>
public
FieldInfo
Field
public
FieldInfo
Field
{
get
;
}
{
get
{
return
_field
;
}
}
/// <summary>
/// <summary>
/// Target constructor parameter
/// Target constructor parameter
/// </summary>
/// </summary>
public
ParameterInfo
Parameter
public
ParameterInfo
Parameter
{
get
;
}
{
get
{
return
_parameter
;
}
}
}
}
}
}
Dapper/SqlDataRecordHandler.cs
View file @
12886d80
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
#if !DNXCORE50
#if !DNXCORE50
namespace
Dapper
namespace
Dapper
{
{
sealed
class
SqlDataRecordHandler
:
Dapper
.
SqlMapper
.
ITypeHandler
sealed
class
SqlDataRecordHandler
:
SqlMapper
.
ITypeHandler
{
{
public
object
Parse
(
Type
destinationType
,
object
value
)
public
object
Parse
(
Type
destinationType
,
object
value
)
{
{
...
...
Dapper/SqlDataRecordListTVPParameter.cs
View file @
12886d80
...
@@ -9,7 +9,7 @@ namespace Dapper
...
@@ -9,7 +9,7 @@ namespace Dapper
/// <summary>
/// <summary>
/// Used to pass a IEnumerable<SqlDataRecord> as a SqlDataRecordListTVPParameter
/// Used to pass a IEnumerable<SqlDataRecord> as a SqlDataRecordListTVPParameter
/// </summary>
/// </summary>
sealed
class
SqlDataRecordListTVPParameter
:
Dapper
.
SqlMapper
.
ICustomQueryParameter
sealed
class
SqlDataRecordListTVPParameter
:
SqlMapper
.
ICustomQueryParameter
{
{
private
readonly
IEnumerable
<
Microsoft
.
SqlServer
.
Server
.
SqlDataRecord
>
data
;
private
readonly
IEnumerable
<
Microsoft
.
SqlServer
.
Server
.
SqlDataRecord
>
data
;
private
readonly
string
typeName
;
private
readonly
string
typeName
;
...
...
Dapper/SqlMapper.Async.cs
View file @
12886d80
...
@@ -60,7 +60,7 @@ public static Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, string
...
@@ -60,7 +60,7 @@ public static Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, string
/// </summary>
/// </summary>
public
static
Task
<
IEnumerable
<
object
>>
QueryAsync
(
this
IDbConnection
cnn
,
Type
type
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
)
public
static
Task
<
IEnumerable
<
object
>>
QueryAsync
(
this
IDbConnection
cnn
,
Type
type
,
string
sql
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
)
{
{
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
if
(
type
==
null
)
throw
new
ArgumentNullException
(
nameof
(
type
)
);
return
QueryAsync
<
object
>(
cnn
,
type
,
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
,
default
(
CancellationToken
)));
return
QueryAsync
<
object
>(
cnn
,
type
,
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
CommandFlags
.
Buffered
,
default
(
CancellationToken
)));
}
}
...
@@ -83,7 +83,7 @@ public static Task<IEnumerable<object>> QueryAsync(this IDbConnection cnn, Type
...
@@ -83,7 +83,7 @@ public static Task<IEnumerable<object>> QueryAsync(this IDbConnection cnn, Type
private
static
async
Task
<
IEnumerable
<
T
>>
QueryAsync
<
T
>(
this
IDbConnection
cnn
,
Type
effectiveType
,
CommandDefinition
command
)
private
static
async
Task
<
IEnumerable
<
T
>>
QueryAsync
<
T
>(
this
IDbConnection
cnn
,
Type
effectiveType
,
CommandDefinition
command
)
{
{
object
param
=
command
.
Parameters
;
object
param
=
command
.
Parameters
;
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
?
.
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
;
var
cancel
=
command
.
CancellationToken
;
...
@@ -177,8 +177,8 @@ private struct AsyncExecState
...
@@ -177,8 +177,8 @@ private struct AsyncExecState
public
readonly
Task
<
int
>
Task
;
public
readonly
Task
<
int
>
Task
;
public
AsyncExecState
(
DbCommand
command
,
Task
<
int
>
task
)
public
AsyncExecState
(
DbCommand
command
,
Task
<
int
>
task
)
{
{
this
.
Command
=
command
;
Command
=
command
;
this
.
Task
=
task
;
Task
=
task
;
}
}
}
}
private
static
async
Task
<
int
>
ExecuteMultiImplAsync
(
IDbConnection
cnn
,
CommandDefinition
command
,
IEnumerable
multiExec
)
private
static
async
Task
<
int
>
ExecuteMultiImplAsync
(
IDbConnection
cnn
,
CommandDefinition
command
,
IEnumerable
multiExec
)
...
@@ -276,7 +276,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
...
@@ -276,7 +276,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
}
}
private
static
async
Task
<
int
>
ExecuteImplAsync
(
IDbConnection
cnn
,
CommandDefinition
command
,
object
param
)
private
static
async
Task
<
int
>
ExecuteImplAsync
(
IDbConnection
cnn
,
CommandDefinition
command
,
object
param
)
{
{
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
null
,
param
==
null
?
null
:
param
.
GetType
(),
null
);
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
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
;
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
...
@@ -542,8 +542,7 @@ private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDat
...
@@ -542,8 +542,7 @@ private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDat
yield
return
(
T
)
func
(
reader
);
yield
return
(
T
)
func
(
reader
);
}
}
while
(
reader
.
NextResult
())
{
}
while
(
reader
.
NextResult
())
{
}
if
(
parameters
is
SqlMapper
.
IParameterCallbacks
)
(
parameters
as
IParameterCallbacks
)?.
OnCompleted
();
((
SqlMapper
.
IParameterCallbacks
)
parameters
).
OnCompleted
();
}
}
}
}
...
@@ -598,7 +597,7 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
...
@@ -598,7 +597,7 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
{
/* don't spoil the existing exception */
}
{
/* don't spoil the existing exception */
}
reader
.
Dispose
();
reader
.
Dispose
();
}
}
if
(
cmd
!=
null
)
cmd
.
Dispose
();
cmd
?
.
Dispose
();
if
(
wasClosed
)
cnn
.
Close
();
if
(
wasClosed
)
cnn
.
Close
();
throw
;
throw
;
}
}
...
@@ -666,7 +665,7 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
...
@@ -666,7 +665,7 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
finally
finally
{
{
if
(
wasClosed
)
cnn
.
Close
();
if
(
wasClosed
)
cnn
.
Close
();
if
(
cmd
!=
null
)
cmd
.
Dispose
();
cmd
?
.
Dispose
();
}
}
}
}
...
@@ -743,7 +742,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman
...
@@ -743,7 +742,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman
finally
finally
{
{
if
(
wasClosed
)
cnn
.
Close
();
if
(
wasClosed
)
cnn
.
Close
();
if
(
cmd
!=
null
)
cmd
.
Dispose
();
cmd
?
.
Dispose
();
}
}
return
Parse
<
T
>(
result
);
return
Parse
<
T
>(
result
);
}
}
...
...
Dapper/SqlMapper.DapperRow.cs
View file @
12886d80
...
@@ -17,8 +17,8 @@ private sealed class DapperRow
...
@@ -17,8 +17,8 @@ private sealed class DapperRow
public
DapperRow
(
DapperTable
table
,
object
[]
values
)
public
DapperRow
(
DapperTable
table
,
object
[]
values
)
{
{
if
(
table
==
null
)
throw
new
ArgumentNullException
(
"table"
);
if
(
table
==
null
)
throw
new
ArgumentNullException
(
nameof
(
table
)
);
if
(
values
==
null
)
throw
new
ArgumentNullException
(
"values"
);
if
(
values
==
null
)
throw
new
ArgumentNullException
(
nameof
(
values
)
);
this
.
table
=
table
;
this
.
table
=
table
;
this
.
values
=
values
;
this
.
values
=
values
;
}
}
...
@@ -136,11 +136,7 @@ IEnumerator IEnumerable.GetEnumerator()
...
@@ -136,11 +136,7 @@ IEnumerator IEnumerable.GetEnumerator()
return
dic
.
Remove
(
item
.
Key
);
return
dic
.
Remove
(
item
.
Key
);
}
}
bool
ICollection
<
KeyValuePair
<
string
,
object
>>.
IsReadOnly
bool
ICollection
<
KeyValuePair
<
string
,
object
>>.
IsReadOnly
=>
false
;
{
get
{
return
false
;
}
}
#
endregion
#
endregion
#
region
Implementation
of
IDictionary
<
string
,
object
>
#
region
Implementation
of
IDictionary
<
string
,
object
>
...
@@ -177,7 +173,7 @@ public object SetValue(string key, object value)
...
@@ -177,7 +173,7 @@ public object SetValue(string key, object value)
}
}
private
object
SetValue
(
string
key
,
object
value
,
bool
isAdd
)
private
object
SetValue
(
string
key
,
object
value
,
bool
isAdd
)
{
{
if
(
key
==
null
)
throw
new
ArgumentNullException
(
"key"
);
if
(
key
==
null
)
throw
new
ArgumentNullException
(
nameof
(
key
)
);
int
index
=
table
.
IndexOfName
(
key
);
int
index
=
table
.
IndexOfName
(
key
);
if
(
index
<
0
)
if
(
index
<
0
)
{
{
...
@@ -186,7 +182,7 @@ private object SetValue(string key, object value, bool isAdd)
...
@@ -186,7 +182,7 @@ private object SetValue(string key, object value, bool isAdd)
else
if
(
isAdd
&&
index
<
values
.
Length
&&
!(
values
[
index
]
is
DeadValue
))
else
if
(
isAdd
&&
index
<
values
.
Length
&&
!(
values
[
index
]
is
DeadValue
))
{
{
// then semantically, this value already exists
// then semantically, this value already exists
throw
new
ArgumentException
(
"An item with the same key has already been added"
,
"key"
);
throw
new
ArgumentException
(
"An item with the same key has already been added"
,
nameof
(
key
)
);
}
}
int
oldLength
=
values
.
Length
;
int
oldLength
=
values
.
Length
;
if
(
oldLength
<=
index
)
if
(
oldLength
<=
index
)
...
...
Dapper/SqlMapper.DataTable.cs
View file @
12886d80
...
@@ -10,11 +10,11 @@ private sealed class DapperTable
...
@@ -10,11 +10,11 @@ private sealed class DapperTable
string
[]
fieldNames
;
string
[]
fieldNames
;
readonly
Dictionary
<
string
,
int
>
fieldNameLookup
;
readonly
Dictionary
<
string
,
int
>
fieldNameLookup
;
internal
string
[]
FieldNames
{
get
{
return
fieldNames
;
}
}
internal
string
[]
FieldNames
=>
fieldNames
;
public
DapperTable
(
string
[]
fieldNames
)
public
DapperTable
(
string
[]
fieldNames
)
{
{
if
(
fieldNames
==
null
)
throw
new
ArgumentNullException
(
"fieldNames"
);
if
(
fieldNames
==
null
)
throw
new
ArgumentNullException
(
nameof
(
fieldNames
)
);
this
.
fieldNames
=
fieldNames
;
this
.
fieldNames
=
fieldNames
;
fieldNameLookup
=
new
Dictionary
<
string
,
int
>(
fieldNames
.
Length
,
StringComparer
.
Ordinal
);
fieldNameLookup
=
new
Dictionary
<
string
,
int
>(
fieldNames
.
Length
,
StringComparer
.
Ordinal
);
...
@@ -33,7 +33,7 @@ internal int IndexOfName(string name)
...
@@ -33,7 +33,7 @@ internal int IndexOfName(string name)
}
}
internal
int
AddField
(
string
name
)
internal
int
AddField
(
string
name
)
{
{
if
(
name
==
null
)
throw
new
ArgumentNullException
(
"name"
);
if
(
name
==
null
)
throw
new
ArgumentNullException
(
nameof
(
name
)
);
if
(
fieldNameLookup
.
ContainsKey
(
name
))
throw
new
InvalidOperationException
(
"Field already exists: "
+
name
);
if
(
fieldNameLookup
.
ContainsKey
(
name
))
throw
new
InvalidOperationException
(
"Field already exists: "
+
name
);
int
oldLen
=
fieldNames
.
Length
;
int
oldLen
=
fieldNames
.
Length
;
Array
.
Resize
(
ref
fieldNames
,
oldLen
+
1
);
// yes, this is sub-optimal, but this is not the expected common case
Array
.
Resize
(
ref
fieldNames
,
oldLen
+
1
);
// yes, this is sub-optimal, but this is not the expected common case
...
@@ -48,7 +48,7 @@ internal bool FieldExists(string key)
...
@@ -48,7 +48,7 @@ internal bool FieldExists(string key)
return
key
!=
null
&&
fieldNameLookup
.
ContainsKey
(
key
);
return
key
!=
null
&&
fieldNameLookup
.
ContainsKey
(
key
);
}
}
public
int
FieldCount
{
get
{
return
fieldNames
.
Length
;
}
}
public
int
FieldCount
=>
fieldNames
.
Length
;
}
}
}
}
...
...
Dapper/SqlMapper.GridReader.Async.cs
View file @
12886d80
...
@@ -45,7 +45,7 @@ public Task<IEnumerable<dynamic>> ReadAsync(bool buffered = true)
...
@@ -45,7 +45,7 @@ public Task<IEnumerable<dynamic>> ReadAsync(bool buffered = true)
/// </summary>
/// </summary>
public
Task
<
IEnumerable
<
object
>>
ReadAsync
(
Type
type
,
bool
buffered
=
true
)
public
Task
<
IEnumerable
<
object
>>
ReadAsync
(
Type
type
,
bool
buffered
=
true
)
{
{
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
if
(
type
==
null
)
throw
new
ArgumentNullException
(
nameof
(
type
)
);
return
ReadAsyncImpl
<
object
>(
type
,
buffered
);
return
ReadAsyncImpl
<
object
>(
type
,
buffered
);
}
}
/// <summary>
/// <summary>
...
@@ -62,7 +62,7 @@ private async Task NextResultAsync()
...
@@ -62,7 +62,7 @@ private async Task NextResultAsync()
{
{
readCount
++;
readCount
++;
gridIndex
++;
gridIndex
++;
c
onsumed
=
false
;
IsC
onsumed
=
false
;
}
}
else
else
{
{
...
@@ -70,7 +70,7 @@ private async Task NextResultAsync()
...
@@ -70,7 +70,7 @@ private async Task NextResultAsync()
// need for "Cancel" etc
// need for "Cancel" etc
reader
.
Dispose
();
reader
.
Dispose
();
reader
=
null
;
reader
=
null
;
if
(
callbacks
!=
null
)
callbacks
.
OnCompleted
();
callbacks
?
.
OnCompleted
();
Dispose
();
Dispose
();
}
}
}
}
...
@@ -78,7 +78,7 @@ private async Task NextResultAsync()
...
@@ -78,7 +78,7 @@ private async Task NextResultAsync()
private
Task
<
IEnumerable
<
T
>>
ReadAsyncImpl
<
T
>(
Type
type
,
bool
buffered
)
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
(
reader
==
null
)
throw
new
ObjectDisposedException
(
GetType
().
FullName
,
"The reader has been disposed; this can happen after all data has been consumed"
);
if
(
c
onsumed
)
throw
new
InvalidOperationException
(
"Query results must be consumed in the correct order, and each result can only be consumed once"
);
if
(
IsC
onsumed
)
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
);
CacheInfo
cache
=
GetCacheInfo
(
typedIdentity
,
null
,
addToCache
);
CacheInfo
cache
=
GetCacheInfo
(
typedIdentity
,
null
,
addToCache
);
var
deserializer
=
cache
.
Deserializer
;
var
deserializer
=
cache
.
Deserializer
;
...
@@ -89,8 +89,8 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
...
@@ -89,8 +89,8 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
type
,
reader
,
0
,
-
1
,
false
));
deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
type
,
reader
,
0
,
-
1
,
false
));
cache
.
Deserializer
=
deserializer
;
cache
.
Deserializer
=
deserializer
;
}
}
c
onsumed
=
true
;
IsC
onsumed
=
true
;
if
(
buffered
&&
this
.
reader
is
DbDataReader
)
if
(
buffered
&&
reader
is
DbDataReader
)
{
{
return
ReadBufferedAsync
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
return
ReadBufferedAsync
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
}
}
...
@@ -104,27 +104,23 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
...
@@ -104,27 +104,23 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
private
async
Task
<
IEnumerable
<
T
>>
ReadBufferedAsync
<
T
>(
int
index
,
Func
<
IDataReader
,
object
>
deserializer
,
Identity
typedIdentity
)
private
async
Task
<
IEnumerable
<
T
>>
ReadBufferedAsync
<
T
>(
int
index
,
Func
<
IDataReader
,
object
>
deserializer
,
Identity
typedIdentity
)
{
{
//
try
try
//
{
{
var
reader
=
(
DbDataReader
)
this
.
reader
;
var
reader
=
(
DbDataReader
)
this
.
reader
;
List
<
T
>
buffer
=
new
List
<
T
>();
List
<
T
>
buffer
=
new
List
<
T
>();
while
(
index
==
gridIndex
&&
await
reader
.
ReadAsync
(
cancel
).
ConfigureAwait
(
false
))
while
(
index
==
gridIndex
&&
await
reader
.
ReadAsync
(
cancel
).
ConfigureAwait
(
false
))
{
{
buffer
.
Add
((
T
)
deserializer
(
reader
));
buffer
.
Add
((
T
)
deserializer
(
reader
));
}
}
if
(
index
==
gridIndex
)
// need to do this outside of the finally pre-C#6
return
buffer
;
}
finally
// finally so that First etc progresses things even when multiple rows
{
if
(
index
==
gridIndex
)
{
{
await
NextResultAsync
().
ConfigureAwait
(
false
);
await
NextResultAsync
().
ConfigureAwait
(
false
);
}
}
return
buffer
;
}
//}
//finally // finally so that First etc progresses things even when multiple rows
//{
// if (index == gridIndex)
// {
// await NextResultAsync().ConfigureAwait(false);
// }
//}
}
}
}
}
...
...
Dapper/SqlMapper.GridReader.cs
View file @
12886d80
...
@@ -27,13 +27,12 @@ partial class SqlMapper
...
@@ -27,13 +27,12 @@ partial class SqlMapper
public
partial
class
GridReader
:
IDisposable
public
partial
class
GridReader
:
IDisposable
{
{
private
IDataReader
reader
;
private
IDataReader
reader
;
private
IDbCommand
command
;
private
Identity
identity
;
private
Identity
identity
;
private
bool
addToCache
;
private
bool
addToCache
;
internal
GridReader
(
IDbCommand
command
,
IDataReader
reader
,
Identity
identity
,
SqlMapper
.
IParameterCallbacks
callbacks
,
bool
addToCache
)
internal
GridReader
(
IDbCommand
command
,
IDataReader
reader
,
Identity
identity
,
IParameterCallbacks
callbacks
,
bool
addToCache
)
{
{
this
.
Command
=
command
;
Command
=
command
;
this
.
reader
=
reader
;
this
.
reader
=
reader
;
this
.
identity
=
identity
;
this
.
identity
=
identity
;
this
.
callbacks
=
callbacks
;
this
.
callbacks
=
callbacks
;
...
@@ -62,14 +61,14 @@ public IEnumerable<T> Read<T>(bool buffered = true)
...
@@ -62,14 +61,14 @@ public IEnumerable<T> Read<T>(bool buffered = true)
/// </summary>
/// </summary>
public
IEnumerable
<
object
>
Read
(
Type
type
,
bool
buffered
=
true
)
public
IEnumerable
<
object
>
Read
(
Type
type
,
bool
buffered
=
true
)
{
{
if
(
type
==
null
)
throw
new
ArgumentNullException
(
"type"
);
if
(
type
==
null
)
throw
new
ArgumentNullException
(
nameof
(
type
)
);
return
ReadImpl
<
object
>(
type
,
buffered
);
return
ReadImpl
<
object
>(
type
,
buffered
);
}
}
private
IEnumerable
<
T
>
ReadImpl
<
T
>(
Type
type
,
bool
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
(
c
onsumed
)
throw
new
InvalidOperationException
(
"Query results must be consumed in the correct order, and each result can only be consumed once"
);
if
(
IsC
onsumed
)
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
);
CacheInfo
cache
=
GetCacheInfo
(
typedIdentity
,
null
,
addToCache
);
CacheInfo
cache
=
GetCacheInfo
(
typedIdentity
,
null
,
addToCache
);
var
deserializer
=
cache
.
Deserializer
;
var
deserializer
=
cache
.
Deserializer
;
...
@@ -80,7 +79,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
...
@@ -80,7 +79,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
type
,
reader
,
0
,
-
1
,
false
));
deserializer
=
new
DeserializerState
(
hash
,
GetDeserializer
(
type
,
reader
,
0
,
-
1
,
false
));
cache
.
Deserializer
=
deserializer
;
cache
.
Deserializer
=
deserializer
;
}
}
c
onsumed
=
true
;
IsC
onsumed
=
true
;
var
result
=
ReadDeferred
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
var
result
=
ReadDeferred
<
T
>(
gridIndex
,
deserializer
.
Func
,
typedIdentity
);
return
buffered
?
result
.
ToList
()
:
result
;
return
buffered
?
result
.
ToList
()
:
result
;
}
}
...
@@ -99,7 +98,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
...
@@ -99,7 +98,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
},
gridIndex
);
},
gridIndex
);
try
try
{
{
foreach
(
var
r
in
SqlMapper
.
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
default
(
CommandDefinition
),
func
,
splitOn
,
reader
,
identity
,
false
))
foreach
(
var
r
in
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
default
(
CommandDefinition
),
func
,
splitOn
,
reader
,
identity
,
false
))
{
{
yield
return
r
;
yield
return
r
;
}
}
...
@@ -115,7 +114,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec
...
@@ -115,7 +114,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec
var
identity
=
this
.
identity
.
ForGrid
(
typeof
(
TReturn
),
types
,
gridIndex
);
var
identity
=
this
.
identity
.
ForGrid
(
typeof
(
TReturn
),
types
,
gridIndex
);
try
try
{
{
foreach
(
var
r
in
SqlMapper
.
MultiMapImpl
<
TReturn
>(
null
,
default
(
CommandDefinition
),
types
,
map
,
splitOn
,
reader
,
identity
,
false
))
foreach
(
var
r
in
MultiMapImpl
<
TReturn
>(
null
,
default
(
CommandDefinition
),
types
,
map
,
splitOn
,
reader
,
identity
,
false
))
{
{
yield
return
r
;
yield
return
r
;
}
}
...
@@ -205,34 +204,17 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese
...
@@ -205,34 +204,17 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese
}
}
}
}
private
int
gridIndex
,
readCount
;
private
int
gridIndex
,
readCount
;
private
bool
consumed
;
private
IParameterCallbacks
callbacks
;
private
SqlMapper
.
IParameterCallbacks
callbacks
;
/// <summary>
/// <summary>
/// Has the underlying reader been consumed?
/// Has the underlying reader been consumed?
/// </summary>
/// </summary>
public
bool
IsConsumed
public
bool
IsConsumed
{
get
;
private
set
;
}
{
get
{
return
consumed
;
}
}
/// <summary>
/// <summary>
/// The command associated with the reader
/// The command associated with the reader
/// </summary>
/// </summary>
public
IDbCommand
Command
public
IDbCommand
Command
{
get
;
set
;
}
{
get
{
return
command
;
}
set
{
command
=
value
;
}
}
private
void
NextResult
()
private
void
NextResult
()
{
{
...
@@ -240,7 +222,7 @@ private void NextResult()
...
@@ -240,7 +222,7 @@ private void NextResult()
{
{
readCount
++;
readCount
++;
gridIndex
++;
gridIndex
++;
c
onsumed
=
false
;
IsC
onsumed
=
false
;
}
}
else
else
{
{
...
@@ -248,7 +230,7 @@ private void NextResult()
...
@@ -248,7 +230,7 @@ private void NextResult()
// need for "Cancel" etc
// need for "Cancel" etc
reader
.
Dispose
();
reader
.
Dispose
();
reader
=
null
;
reader
=
null
;
if
(
callbacks
!=
null
)
callbacks
.
OnCompleted
();
callbacks
?
.
OnCompleted
();
Dispose
();
Dispose
();
}
}
}
}
...
@@ -259,7 +241,7 @@ public void Dispose()
...
@@ -259,7 +241,7 @@ public void Dispose()
{
{
if
(
reader
!=
null
)
if
(
reader
!=
null
)
{
{
if
(!
reader
.
IsClosed
&&
Command
!=
null
)
Command
.
Cancel
();
if
(!
reader
.
IsClosed
)
Command
?
.
Cancel
();
reader
.
Dispose
();
reader
.
Dispose
();
reader
=
null
;
reader
=
null
;
}
}
...
...
Dapper/SqlMapper.Identity.cs
View file @
12886d80
...
@@ -58,17 +58,17 @@ private Identity(string sql, CommandType? commandType, string connectionString,
...
@@ -58,17 +58,17 @@ private Identity(string sql, CommandType? commandType, string connectionString,
hashCode
=
17
;
// we *know* we are using this in a dictionary, so pre-compute this
hashCode
=
17
;
// we *know* we are using this in a dictionary, so pre-compute this
hashCode
=
hashCode
*
23
+
commandType
.
GetHashCode
();
hashCode
=
hashCode
*
23
+
commandType
.
GetHashCode
();
hashCode
=
hashCode
*
23
+
gridIndex
.
GetHashCode
();
hashCode
=
hashCode
*
23
+
gridIndex
.
GetHashCode
();
hashCode
=
hashCode
*
23
+
(
sql
==
null
?
0
:
sql
.
GetHashCode
()
);
hashCode
=
hashCode
*
23
+
(
sql
?.
GetHashCode
()
??
0
);
hashCode
=
hashCode
*
23
+
(
type
==
null
?
0
:
type
.
GetHashCode
()
);
hashCode
=
hashCode
*
23
+
(
type
?.
GetHashCode
()
??
0
);
if
(
otherTypes
!=
null
)
if
(
otherTypes
!=
null
)
{
{
foreach
(
var
t
in
otherTypes
)
foreach
(
var
t
in
otherTypes
)
{
{
hashCode
=
hashCode
*
23
+
(
t
==
null
?
0
:
t
.
GetHashCode
()
);
hashCode
=
hashCode
*
23
+
(
t
?.
GetHashCode
()
??
0
);
}
}
}
}
hashCode
=
hashCode
*
23
+
(
connectionString
==
null
?
0
:
SqlMapper
.
connectionStringComparer
.
GetHashCode
(
connectionString
));
hashCode
=
hashCode
*
23
+
(
connectionString
==
null
?
0
:
connectionStringComparer
.
GetHashCode
(
connectionString
));
hashCode
=
hashCode
*
23
+
(
parametersType
==
null
?
0
:
parametersType
.
GetHashCode
()
);
hashCode
=
hashCode
*
23
+
(
parametersType
?.
GetHashCode
()
??
0
);
}
}
}
}
...
@@ -127,7 +127,7 @@ public bool Equals(Identity other)
...
@@ -127,7 +127,7 @@ public bool Equals(Identity other)
type
==
other
.
type
&&
type
==
other
.
type
&&
sql
==
other
.
sql
&&
sql
==
other
.
sql
&&
commandType
==
other
.
commandType
&&
commandType
==
other
.
commandType
&&
SqlMapper
.
connectionStringComparer
.
Equals
(
connectionString
,
other
.
connectionString
)
&&
connectionStringComparer
.
Equals
(
connectionString
,
other
.
connectionString
)
&&
parametersType
==
other
.
parametersType
;
parametersType
==
other
.
parametersType
;
}
}
}
}
...
...
Dapper/SqlMapper.Link.cs
View file @
12886d80
...
@@ -49,9 +49,9 @@ private Link(TKey key, TValue value, Link<TKey, TValue> tail)
...
@@ -49,9 +49,9 @@ private Link(TKey key, TValue value, Link<TKey, TValue> tail)
Value
=
value
;
Value
=
value
;
Tail
=
tail
;
Tail
=
tail
;
}
}
public
TKey
Key
{
get
;
private
set
;
}
public
TKey
Key
{
get
;
}
public
TValue
Value
{
get
;
private
set
;
}
public
TValue
Value
{
get
;
}
public
Link
<
TKey
,
TValue
>
Tail
{
get
;
private
set
;
}
public
Link
<
TKey
,
TValue
>
Tail
{
get
;
}
}
}
}
}
}
}
Dapper/SqlMapper.LiteralToken.cs
View file @
12886d80
...
@@ -9,20 +9,20 @@ partial class SqlMapper
...
@@ -9,20 +9,20 @@ partial class SqlMapper
/// </summary>
/// </summary>
internal
struct
LiteralToken
internal
struct
LiteralToken
{
{
private
readonly
string
token
,
member
;
/// <summary>
/// <summary>
/// The text in the original command that should be replaced
/// The text in the original command that should be replaced
/// </summary>
/// </summary>
public
string
Token
{
get
{
return
token
;
}
}
public
string
Token
{
get
;
}
/// <summary>
/// <summary>
/// The name of the member referred to by the token
/// The name of the member referred to by the token
/// </summary>
/// </summary>
public
string
Member
{
get
{
return
member
;
}
}
public
string
Member
{
get
;
}
internal
LiteralToken
(
string
token
,
string
member
)
internal
LiteralToken
(
string
token
,
string
member
)
{
{
this
.
t
oken
=
token
;
T
oken
=
token
;
this
.
m
ember
=
member
;
M
ember
=
member
;
}
}
internal
static
readonly
IList
<
LiteralToken
>
None
=
new
LiteralToken
[
0
];
internal
static
readonly
IList
<
LiteralToken
>
None
=
new
LiteralToken
[
0
];
...
...
Dapper/SqlMapper.cs
View file @
12886d80
This diff is collapsed.
Click to expand it.
Dapper/TableValuedParameter.cs
View file @
12886d80
...
@@ -8,7 +8,7 @@ namespace Dapper
...
@@ -8,7 +8,7 @@ namespace Dapper
/// <summary>
/// <summary>
/// Used to pass a DataTable as a TableValuedParameter
/// Used to pass a DataTable as a TableValuedParameter
/// </summary>
/// </summary>
sealed
class
TableValuedParameter
:
Dapper
.
SqlMapper
.
ICustomQueryParameter
sealed
class
TableValuedParameter
:
SqlMapper
.
ICustomQueryParameter
{
{
private
readonly
DataTable
table
;
private
readonly
DataTable
table
;
private
readonly
string
typeName
;
private
readonly
string
typeName
;
...
@@ -47,14 +47,14 @@ internal static void Set(IDbDataParameter parameter, DataTable table, string typ
...
@@ -47,14 +47,14 @@ internal static void Set(IDbDataParameter parameter, DataTable table, string typ
parameter
.
Value
=
SqlMapper
.
SanitizeParameterValue
(
table
);
parameter
.
Value
=
SqlMapper
.
SanitizeParameterValue
(
table
);
if
(
string
.
IsNullOrEmpty
(
typeName
)
&&
table
!=
null
)
if
(
string
.
IsNullOrEmpty
(
typeName
)
&&
table
!=
null
)
{
{
typeName
=
SqlMapper
.
GetTypeName
(
table
);
typeName
=
table
.
GetTypeName
(
);
}
}
if
(!
string
.
IsNullOrEmpty
(
typeName
))
if
(!
string
.
IsNullOrEmpty
(
typeName
))
{
{
var
sqlParam
=
parameter
as
System
.
Data
.
SqlClient
.
SqlParameter
;
var
sqlParam
=
parameter
as
System
.
Data
.
SqlClient
.
SqlParameter
;
if
(
sqlParam
!=
null
)
if
(
sqlParam
!=
null
)
{
{
if
(
setTypeName
!=
null
)
setTypeNam
e
(
sqlParam
,
typeName
);
setTypeName
?.
Invok
e
(
sqlParam
,
typeName
);
sqlParam
.
SqlDbType
=
SqlDbType
.
Structured
;
sqlParam
.
SqlDbType
=
SqlDbType
.
Structured
;
}
}
}
}
...
...
Dapper/WrappedReader.cs
View file @
12886d80
...
@@ -252,23 +252,17 @@ public WrappedReader(IDbCommand cmd, IDataReader reader)
...
@@ -252,23 +252,17 @@ public WrappedReader(IDbCommand cmd, IDataReader reader)
void
IDataReader
.
Close
()
void
IDataReader
.
Close
()
{
{
if
(
reader
!=
null
)
reader
.
Close
();
reader
?
.
Close
();
}
}
int
IDataReader
.
Depth
int
IDataReader
.
Depth
=>
Reader
.
Depth
;
{
get
{
return
Reader
.
Depth
;
}
}
DataTable
IDataReader
.
GetSchemaTable
()
DataTable
IDataReader
.
GetSchemaTable
()
{
{
return
Reader
.
GetSchemaTable
();
return
Reader
.
GetSchemaTable
();
}
}
bool
IDataReader
.
IsClosed
bool
IDataReader
.
IsClosed
=>
reader
?.
IsClosed
??
true
;
{
get
{
return
reader
==
null
?
true
:
reader
.
IsClosed
;
}
}
bool
IDataReader
.
NextResult
()
bool
IDataReader
.
NextResult
()
{
{
...
@@ -280,24 +274,18 @@ bool IDataReader.Read()
...
@@ -280,24 +274,18 @@ bool IDataReader.Read()
return
Reader
.
Read
();
return
Reader
.
Read
();
}
}
int
IDataReader
.
RecordsAffected
int
IDataReader
.
RecordsAffected
=>
Reader
.
RecordsAffected
;
{
get
{
return
Reader
.
RecordsAffected
;
}
}
void
IDisposable
.
Dispose
()
void
IDisposable
.
Dispose
()
{
{
if
(
reader
!=
null
)
reader
.
Close
();
reader
?
.
Close
();
if
(
reader
!=
null
)
reader
.
Dispose
();
reader
?
.
Dispose
();
reader
=
null
;
reader
=
null
;
if
(
cmd
!=
null
)
cmd
.
Dispose
();
cmd
?
.
Dispose
();
cmd
=
null
;
cmd
=
null
;
}
}
int
IDataRecord
.
FieldCount
int
IDataRecord
.
FieldCount
=>
Reader
.
FieldCount
;
{
get
{
return
Reader
.
FieldCount
;
}
}
bool
IDataRecord
.
GetBoolean
(
int
i
)
bool
IDataRecord
.
GetBoolean
(
int
i
)
{
{
...
@@ -409,15 +397,9 @@ bool IDataRecord.IsDBNull(int i)
...
@@ -409,15 +397,9 @@ bool IDataRecord.IsDBNull(int i)
return
Reader
.
IsDBNull
(
i
);
return
Reader
.
IsDBNull
(
i
);
}
}
object
IDataRecord
.
this
[
string
name
]
object
IDataRecord
.
this
[
string
name
]
=>
Reader
[
name
];
{
get
{
return
Reader
[
name
];
}
}
object
IDataRecord
.
this
[
int
i
]
object
IDataRecord
.
this
[
int
i
]
=>
Reader
[
i
];
{
get
{
return
Reader
[
i
];
}
}
}
}
#endif
#endif
}
}
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