Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Dapper
提交
9d7e6589
D
Dapper
项目概览
int
/
Dapper
大约 1 年 前同步成功
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Dapper
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9d7e6589
编写于
4月 26, 2011
作者:
S
Sam Saffron
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dynamic multi deserialization for extra awesome
bug fix around null objects
上级
20b9ec35
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
92 addition
and
13 deletion
+92
-13
Dapper/SqlMapper.cs
Dapper/SqlMapper.cs
+51
-12
Tests/Tests.cs
Tests/Tests.cs
+41
-1
未找到文件。
Dapper/SqlMapper.cs
浏览文件 @
9d7e6589
...
...
@@ -227,8 +227,25 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
}
}
info
.
Deserializer
=
GetDeserializer
<
T
>(
identity
,
reader
,
start
,
length
);
info
.
Deserializer2
=
GetDeserializer
<
U
>(
identity
,
reader
,
start
+
length
);
// dynamic comes back as object ...
if
(
typeof
(
T
)
==
typeof
(
object
))
{
info
.
Deserializer
=
GetDeserializer
<
ExpandoObject
>(
identity
,
reader
,
start
,
length
);
}
else
{
info
.
Deserializer
=
GetDeserializer
<
T
>(
identity
,
reader
,
start
,
length
);
}
if
(
typeof
(
U
)
==
typeof
(
object
))
{
info
.
Deserializer2
=
GetDeserializer
<
ExpandoObject
>(
identity
,
reader
,
start
+
length
,
returnNullIfFirstMissing
:
true
);
}
else
{
info
.
Deserializer2
=
GetDeserializer
<
U
>(
identity
,
reader
,
start
+
length
,
returnNullIfFirstMissing
:
true
);
}
queryCache
[
identity
]
=
info
;
}
...
...
@@ -259,22 +276,22 @@ private static CacheInfo GetCacheInfo(object param, Identity identity)
}
static
class
DynamicStub
class
DynamicStub
{
public
static
Type
Type
=
typeof
(
DynamicStub
);
}
static
Func
<
IDataReader
,
T
>
GetDeserializer
<
T
>(
Identity
identity
,
IDataReader
reader
,
int
startBound
=
0
,
int
length
=
-
1
)
static
Func
<
IDataReader
,
T
>
GetDeserializer
<
T
>(
Identity
identity
,
IDataReader
reader
,
int
startBound
=
0
,
int
length
=
-
1
,
bool
returnNullIfFirstMissing
=
false
)
{
object
oDeserializer
;
if
(
typeof
(
T
)
==
DynamicStub
.
Type
||
typeof
(
T
)
==
typeof
(
ExpandoObject
))
{
oDeserializer
=
GetDynamicDeserializer
(
reader
);
oDeserializer
=
GetDynamicDeserializer
(
reader
,
startBound
,
length
,
returnNullIfFirstMissing
);
}
else
if
(
typeof
(
T
).
IsClass
&&
typeof
(
T
)
!=
typeof
(
string
))
{
oDeserializer
=
GetClassDeserializer
<
T
>(
reader
,
startBound
,
length
);
oDeserializer
=
GetClassDeserializer
<
T
>(
reader
,
startBound
,
length
,
returnNullIfFirstMissing
:
returnNullIfFirstMissing
);
}
else
{
...
...
@@ -285,10 +302,16 @@ static class DynamicStub
return
deserializer
;
}
private
static
object
GetDynamicDeserializer
(
IDataReader
reader
)
private
static
object
GetDynamicDeserializer
(
IDataReader
reader
,
int
startBound
=
0
,
int
length
=
-
1
,
bool
returnNullIfFirstMissing
=
false
)
{
List
<
string
>
colNames
=
new
List
<
string
>();
for
(
int
i
=
0
;
i
<
reader
.
FieldCount
;
i
++)
if
(
length
==
-
1
)
{
length
=
reader
.
FieldCount
-
startBound
;
}
for
(
int
i
=
startBound
;
i
<
startBound
+
length
;
i
++)
{
colNames
.
Add
(
reader
.
GetName
(
i
));
}
...
...
@@ -297,12 +320,19 @@ private static object GetDynamicDeserializer(IDataReader reader)
r
=>
{
IDictionary
<
string
,
object
>
row
=
new
ExpandoObject
();
int
i
=
0
;
int
i
=
startBound
;
bool
first
=
true
;
foreach
(
var
colName
in
colNames
)
{
var
tmp
=
r
.
GetValue
(
i
);
row
[
colName
]
=
tmp
==
DBNull
.
Value
?
null
:
tmp
;
tmp
=
tmp
==
DBNull
.
Value
?
null
:
tmp
;
row
[
colName
]
=
tmp
;
if
(
returnNullIfFirstMissing
&&
first
&&
tmp
==
null
)
{
return
null
;
}
i
++;
first
=
false
;
}
return
(
ExpandoObject
)
row
;
};
...
...
@@ -521,7 +551,7 @@ private static object GetStructDeserializer<T>(IDataReader reader)
return
deserializer
;
}
public
static
Func
<
IDataReader
,
T
>
GetClassDeserializer
<
T
>(
IDataReader
reader
,
int
startBound
=
0
,
int
length
=
-
1
)
public
static
Func
<
IDataReader
,
T
>
GetClassDeserializer
<
T
>(
IDataReader
reader
,
int
startBound
=
0
,
int
length
=
-
1
,
bool
returnNullIfFirstMissing
=
false
)
{
DynamicMethod
dm
=
new
DynamicMethod
(
"Deserialize"
+
Guid
.
NewGuid
().
ToString
(),
typeof
(
T
),
new
Type
[]
{
typeof
(
IDataReader
)
},
true
);
...
...
@@ -560,6 +590,7 @@ private static object GetStructDeserializer<T>(IDataReader reader)
// stack is empty
il
.
Emit
(
OpCodes
.
Newobj
,
typeof
(
T
).
GetConstructor
(
Type
.
EmptyTypes
));
// stack is now [target]
bool
first
=
true
;
foreach
(
var
item
in
setters
)
{
if
(
item
.
Info
!=
null
)
...
...
@@ -581,13 +612,21 @@ private static object GetStructDeserializer<T>(IDataReader reader)
il
.
Emit
(
OpCodes
.
Callvirt
,
item
.
Info
.
Setter
);
// stack is now [target]
il
.
Emit
(
OpCodes
.
Br_S
,
finishLabel
);
// stack is now [target]
il
.
MarkLabel
(
isDbNullLabel
);
// incoming stack: [target][target][value]
il
.
Emit
(
OpCodes
.
Pop
);
// stack is now [target][target]
il
.
Emit
(
OpCodes
.
Pop
);
// stack is now [target]
if
(
first
&&
returnNullIfFirstMissing
)
{
il
.
Emit
(
OpCodes
.
Pop
);
il
.
Emit
(
OpCodes
.
Ldnull
);
// stack is now [null]
il
.
Emit
(
OpCodes
.
Ret
);
}
il
.
MarkLabel
(
finishLabel
);
}
first
=
false
;
index
+=
1
;
}
il
.
Emit
(
OpCodes
.
Ret
);
// stack is empty
...
...
Tests/Tests.cs
浏览文件 @
9d7e6589
...
...
@@ -269,13 +269,53 @@ public void TestMultiMap()
left join #Users u on u.Id = p.OwnerId
Order by p.Id"
;
var
data
=
connection
.
Query
<
Post
,
User
>(
sql
,
(
post
,
user
)
=>
{
post
.
Owner
=
user
;
});
var
data
=
connection
.
Query
<
Post
,
User
>(
sql
,
(
post
,
user
)
=>
{
post
.
Owner
=
user
;
})
.
ToList
()
;
var
p
=
data
.
First
();
p
.
Content
.
IsEqualTo
(
"Sams Post1"
);
p
.
Id
.
IsEqualTo
(
1
);
p
.
Owner
.
Name
.
IsEqualTo
(
"Sam"
);
p
.
Owner
.
Id
.
IsEqualTo
(
99
);
data
[
2
].
Owner
.
IsNull
();
connection
.
Execute
(
"drop table #Users drop table #Posts"
);
}
public
void
TestMultiMapDynamic
()
{
var
createSql
=
@"
create table #Users (Id int, Name varchar(20))
create table #Posts (Id int, OwnerId int, Content varchar(20))
insert #Users values(99, 'Sam')
insert #Users values(2, 'I am')
insert #Posts values(1, 99, 'Sams Post1')
insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')
"
;
connection
.
Execute
(
createSql
);
var
sql
=
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id"
;
var
data
=
connection
.
Query
<
dynamic
,
dynamic
>(
sql
,
(
post
,
user
)
=>
{
post
.
Owner
=
user
;
}).
ToList
();
var
p
=
data
.
First
();
// hairy extension method support for dynamics
((
string
)
p
.
Content
).
IsEqualTo
(
"Sams Post1"
);
((
int
)
p
.
Id
).
IsEqualTo
(
1
);
((
string
)
p
.
Owner
.
Name
).
IsEqualTo
(
"Sam"
);
((
int
)
p
.
Owner
.
Id
).
IsEqualTo
(
99
);
((
object
)
data
[
2
].
Owner
).
IsNull
();
connection
.
Execute
(
"drop table #Users drop table #Posts"
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录