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
d8125809
Commit
d8125809
authored
Apr 04, 2011
by
Sam Saffron
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support for string lists
support for expando
parent
4ad839b3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
139 additions
and
36 deletions
+139
-36
SqlMapper.cs
SqlMapper.cs
+71
-11
Tests.cs
Tests.cs
+68
-25
No files found.
SqlMapper.cs
View file @
d8125809
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
using
System.Data
;
using
System.Data
;
using
System.Reflection
;
using
System.Reflection
;
using
Microsoft.SqlServer.Server
;
using
Microsoft.SqlServer.Server
;
using
System.
Security.Cryptography
;
using
System.
Dynamic
;
namespace
SqlMapper
namespace
SqlMapper
{
{
...
@@ -32,6 +32,8 @@ static SqlMapper()
...
@@ -32,6 +32,8 @@ static SqlMapper()
typeMap
[
typeof
(
Guid
?)]
=
SqlDbType
.
UniqueIdentifier
;
typeMap
[
typeof
(
Guid
?)]
=
SqlDbType
.
UniqueIdentifier
;
typeMap
[
typeof
(
int
[])]
=
SqlDbType
.
Structured
;
typeMap
[
typeof
(
int
[])]
=
SqlDbType
.
Structured
;
typeMap
[
typeof
(
List
<
int
>)]
=
SqlDbType
.
Structured
;
typeMap
[
typeof
(
List
<
int
>)]
=
SqlDbType
.
Structured
;
typeMap
[
typeof
(
string
[])]
=
SqlDbType
.
Structured
;
typeMap
[
typeof
(
List
<
string
>)]
=
SqlDbType
.
Structured
;
}
}
...
@@ -43,7 +45,7 @@ private ParamInfo()
...
@@ -43,7 +45,7 @@ private ParamInfo()
public
static
ParamInfo
Create
(
string
name
,
SqlDbType
type
,
object
val
)
public
static
ParamInfo
Create
(
string
name
,
SqlDbType
type
,
object
val
)
{
{
return
new
ParamInfo
{
Name
=
name
,
Type
=
type
,
Val
=
val
};
return
new
ParamInfo
{
Name
=
name
,
Type
=
type
,
Val
=
val
};
}
}
public
SqlDbType
Type
{
get
;
private
set
;
}
public
SqlDbType
Type
{
get
;
private
set
;
}
...
@@ -53,7 +55,6 @@ public static ParamInfo Create(string name, SqlDbType type, object val)
...
@@ -53,7 +55,6 @@ public static ParamInfo Create(string name, SqlDbType type, object val)
private
class
Identity
:
IEquatable
<
Identity
>
private
class
Identity
:
IEquatable
<
Identity
>
{
{
public
Type
Type
{
get
{
return
type
;
}
}
public
Type
Type
{
get
{
return
type
;
}
}
public
string
Sql
{
get
{
return
sql
;
}
}
public
string
Sql
{
get
{
return
sql
;
}
}
...
@@ -89,6 +90,12 @@ public bool Equals(Identity other)
...
@@ -89,6 +90,12 @@ public bool Equals(Identity other)
static
Dictionary
<
Type
,
SqlDbType
>
typeMap
;
static
Dictionary
<
Type
,
SqlDbType
>
typeMap
;
public
static
List
<
dynamic
>
ExecuteMapperQuery
(
this
SqlConnection
cnn
,
string
sql
,
object
param
=
null
,
SqlTransaction
transaction
=
null
)
{
// TODO: get rid of casting hackery
return
ExecuteMapperQuery
<
ExpandoObject
>(
cnn
,
sql
,
param
,
transaction
).
Select
(
s
=>
s
as
dynamic
).
ToList
();
}
public
static
List
<
T
>
ExecuteMapperQuery
<
T
>(
this
SqlConnection
cnn
,
string
sql
,
object
param
=
null
,
SqlTransaction
transaction
=
null
)
public
static
List
<
T
>
ExecuteMapperQuery
<
T
>(
this
SqlConnection
cnn
,
string
sql
,
object
param
=
null
,
SqlTransaction
transaction
=
null
)
{
{
var
identity
=
new
Identity
(
sql
,
typeof
(
T
));
var
identity
=
new
Identity
(
sql
,
typeof
(
T
));
...
@@ -114,7 +121,11 @@ public static List<T> ExecuteMapperQuery<T>(this SqlConnection cnn, string sql,
...
@@ -114,7 +121,11 @@ public static List<T> ExecuteMapperQuery<T>(this SqlConnection cnn, string sql,
object
oDeserializer
;
object
oDeserializer
;
if
(!
cachedSerializers
.
TryGetValue
(
identity
,
out
oDeserializer
))
if
(!
cachedSerializers
.
TryGetValue
(
identity
,
out
oDeserializer
))
{
{
if
(
typeof
(
T
).
IsClass
&&
typeof
(
T
)
!=
typeof
(
string
))
if
(
typeof
(
T
)
==
typeof
(
ExpandoObject
))
{
oDeserializer
=
GetDynamicDeserializer
(
reader
);
}
else
if
(
typeof
(
T
).
IsClass
&&
typeof
(
T
)
!=
typeof
(
string
))
{
{
oDeserializer
=
GetClassDeserializer
<
T
>(
reader
);
oDeserializer
=
GetClassDeserializer
<
T
>(
reader
);
}
}
...
@@ -137,6 +148,31 @@ public static List<T> ExecuteMapperQuery<T>(this SqlConnection cnn, string sql,
...
@@ -137,6 +148,31 @@ public static List<T> ExecuteMapperQuery<T>(this SqlConnection cnn, string sql,
return
rval
;
return
rval
;
}
}
private
static
object
GetDynamicDeserializer
(
SqlDataReader
reader
)
{
List
<
string
>
colNames
=
new
List
<
string
>();
for
(
int
i
=
0
;
i
<
reader
.
FieldCount
;
i
++)
{
colNames
.
Add
(
reader
.
GetName
(
i
));
}
Func
<
SqlDataReader
,
ExpandoObject
>
rval
=
r
=>
{
IDictionary
<
string
,
object
>
row
=
new
ExpandoObject
();
int
i
=
0
;
foreach
(
var
colName
in
colNames
)
{
var
tmp
=
reader
.
GetValue
(
i
);
row
[
colName
]
=
tmp
==
DBNull
.
Value
?
null
:
tmp
;
i
++;
}
return
(
ExpandoObject
)
row
;
};
return
rval
;
}
private
static
Func
<
object
,
List
<
ParamInfo
>>
CreateParamInfoGenerator
(
Type
type
)
private
static
Func
<
object
,
List
<
ParamInfo
>>
CreateParamInfoGenerator
(
Type
type
)
{
{
DynamicMethod
dm
=
new
DynamicMethod
(
"ParamInfo"
+
Guid
.
NewGuid
().
ToString
(),
typeof
(
List
<
ParamInfo
>),
new
Type
[]
{
typeof
(
object
)
},
true
);
DynamicMethod
dm
=
new
DynamicMethod
(
"ParamInfo"
+
Guid
.
NewGuid
().
ToString
(),
typeof
(
List
<
ParamInfo
>),
new
Type
[]
{
typeof
(
object
)
},
true
);
...
@@ -195,17 +231,41 @@ private static SqlDataReader GetReader<T>(SqlConnection cnn, SqlTransaction tran
...
@@ -195,17 +231,41 @@ private static SqlDataReader GetReader<T>(SqlConnection cnn, SqlTransaction tran
if
(
info
.
Type
==
SqlDbType
.
Structured
)
if
(
info
.
Type
==
SqlDbType
.
Structured
)
{
{
List
<
SqlDataRecord
>
items
=
new
List
<
SqlDataRecord
>();
List
<
SqlDataRecord
>
items
=
new
List
<
SqlDataRecord
>();
SqlMetaData
[]
metadata
=
{
new
SqlMetaData
(
"Id"
,
SqlDbType
.
Int
)
};
SqlMetaData
[]
metadata
;
foreach
(
int
id
in
(
IEnumerable
<
int
>)
info
.
Val
)
var
intList
=
info
.
Val
as
IEnumerable
<
int
>;
if
(
intList
!=
null
)
{
metadata
=
new
[]
{
new
SqlMetaData
(
"Id"
,
SqlDbType
.
Int
)
};
foreach
(
int
id
in
intList
)
{
SqlDataRecord
rec
=
new
SqlDataRecord
(
metadata
);
rec
.
SetInt32
(
0
,
id
);
items
.
Add
(
rec
);
}
param
.
TypeName
=
"int_list"
;
}
else
{
{
SqlDataRecord
rec
=
new
SqlDataRecord
(
metadata
);
var
strList
=
info
.
Val
as
IEnumerable
<
string
>;
rec
.
SetInt32
(
0
,
id
);
if
(
strList
!=
null
)
items
.
Add
(
rec
);
{
metadata
=
new
[]
{
new
SqlMetaData
(
"Name"
,
SqlDbType
.
NVarChar
,
4000
)
};
foreach
(
var
str
in
strList
)
{
SqlDataRecord
rec
=
new
SqlDataRecord
(
metadata
);
rec
.
SetString
(
0
,
str
);
items
.
Add
(
rec
);
}
param
.
TypeName
=
"string_list"
;
}
else
{
throw
new
NotImplementedException
();
}
}
}
param
.
Direction
=
ParameterDirection
.
Input
;
param
.
Direction
=
ParameterDirection
.
Input
;
param
.
TypeName
=
"int_list"
;
param
.
Value
=
items
;
param
.
Value
=
items
;
}
}
}
}
...
...
Tests.cs
View file @
d8125809
...
@@ -6,61 +6,77 @@
...
@@ -6,61 +6,77 @@
namespace
SqlMapper
namespace
SqlMapper
{
{
class
Test
s
static
class
TestAssertion
s
{
{
void
AssertEquals
(
object
a
,
object
b
)
public
static
void
IsEquals
<
T
>(
this
T
obj
,
T
other
)
{
if
(!
obj
.
Equals
(
other
))
{
throw
new
ApplicationException
(
string
.
Format
(
"{0} should be equals to {1}"
,
obj
,
other
));
}
}
public
static
void
IsSequenceEqual
<
T
>(
this
IEnumerable
<
T
>
obj
,
IEnumerable
<
T
>
other
)
{
{
if
(!
a
.
Equals
(
b
))
if
(!
obj
.
SequenceEqual
(
other
))
{
{
throw
new
ApplicationException
(
string
.
Format
(
"{0} should be equals to {1}"
,
a
,
b
));
throw
new
ApplicationException
(
string
.
Format
(
"{0} should be equals to {1}"
,
obj
,
other
));
}
}
}
}
void
AssertNull
(
object
a
)
public
static
void
IsFalse
(
this
bool
b
)
{
{
if
(
a
!=
null
)
if
(
b
)
{
{
throw
new
ApplicationException
(
string
.
Format
(
"{0} should be null"
,
a
)
);
throw
new
ApplicationException
(
"Expected false"
);
}
}
}
}
public
static
void
IsNull
(
this
object
obj
)
{
if
(
obj
!=
null
)
{
throw
new
ApplicationException
(
"Expected null"
);
}
}
}
class
Tests
{
SqlConnection
connection
=
Program
.
GetOpenConnection
();
SqlConnection
connection
=
Program
.
GetOpenConnection
();
public
void
SelectListInt
()
public
void
SelectListInt
()
{
{
var
items
=
connection
.
ExecuteMapperQuery
<
int
>(
"select 1 union all select 2 union all select 3"
).
ToList
();
connection
.
ExecuteMapperQuery
<
int
>(
"select 1 union all select 2 union all select 3"
)
.
IsSequenceEqual
(
new
[]
{
1
,
2
,
3
});
AssertEquals
(
items
[
0
],
1
);
AssertEquals
(
items
[
1
],
2
);
AssertEquals
(
items
[
2
],
3
);
}
}
public
void
PassInIntArray
()
public
void
PassInIntArray
()
{
{
var
items
=
connection
.
ExecuteMapperQuery
<
int
>(
"select * from @Ids"
,
new
{
Ids
=
new
int
[]
{
1
,
2
,
3
}
}).
ToList
();
connection
.
ExecuteMapperQuery
<
int
>(
"select * from @Ids"
,
new
{
Ids
=
new
int
[]
{
1
,
2
,
3
}
})
.
IsSequenceEqual
(
new
[]
{
1
,
2
,
3
});
AssertEquals
(
items
[
0
],
1
);
AssertEquals
(
items
[
1
],
2
);
AssertEquals
(
items
[
2
],
3
);
}
}
public
void
TestDoubleParam
()
public
void
TestDoubleParam
()
{
{
AssertEquals
(
connection
.
ExecuteMapperQuery
<
double
>(
"select @d"
,
new
{
d
=
0.1d
}).
First
(),
0.1d
);
connection
.
ExecuteMapperQuery
<
double
>(
"select @d"
,
new
{
d
=
0.1d
}).
First
()
.
IsEquals
(
0.1d
);
}
}
public
void
TestBoolParam
()
public
void
TestBoolParam
()
{
{
AssertEquals
(
connection
.
ExecuteMapperQuery
<
bool
>(
"select @b"
,
new
{
b
=
false
}).
First
(),
false
);
connection
.
ExecuteMapperQuery
<
bool
>(
"select @b"
,
new
{
b
=
false
}).
First
()
.
IsFalse
();
}
}
public
void
TestStrings
()
public
void
TestStrings
()
{
{
var
strings
=
connection
.
ExecuteMapperQuery
<
string
>(
@"select 'a' a union select 'b'"
).
ToList
();
connection
.
ExecuteMapperQuery
<
string
>(
@"select 'a' a union select 'b'"
)
AssertEquals
(
strings
[
0
],
"a"
);
.
IsSequenceEqual
(
new
[]
{
"a"
,
"b"
});
AssertEquals
(
strings
[
1
],
"b"
);
}
}
public
class
Dog
public
class
Dog
...
@@ -76,9 +92,36 @@ public class Dog
...
@@ -76,9 +92,36 @@ public class Dog
public
void
TestIntSupportsNull
()
public
void
TestIntSupportsNull
()
{
{
var
dog
=
connection
.
ExecuteMapperQuery
<
Dog
>(
"select Age = @Age"
,
new
{
Age
=
(
int
?)
null
});
var
dog
=
connection
.
ExecuteMapperQuery
<
Dog
>(
"select Age = @Age"
,
new
{
Age
=
(
int
?)
null
});
AssertEquals
(
dog
.
Count
(),
1
);
AssertNull
(
dog
.
First
().
Age
);
dog
.
Count
()
.
IsEquals
(
1
);
dog
.
First
().
Age
.
IsNull
();
}
public
void
TestExpando
()
{
var
rows
=
connection
.
ExecuteMapperQuery
(
"select 1 A, 2 B union all select 3, 4"
);
((
int
)
rows
[
0
].
A
)
.
IsEquals
(
1
);
((
int
)
rows
[
0
].
B
)
.
IsEquals
(
2
);
((
int
)
rows
[
1
].
A
)
.
IsEquals
(
3
);
((
int
)
rows
[
1
].
B
)
.
IsEquals
(
4
);
}
}
public
void
TestStringList
()
{
connection
.
ExecuteMapperQuery
<
string
>(
"select * from @strings"
,
new
{
strings
=
new
[]
{
"a"
,
"b"
,
"c"
}})
.
IsSequenceEqual
(
new
[]
{
"a"
,
"b"
,
"c"
});
}
}
}
}
}
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