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
b2952360
Commit
b2952360
authored
Sep 15, 2014
by
Marc Gravell
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'Polylytics-arbitrary-multi-maps'
parents
f8a189a9
3cd31e42
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
9204 additions
and
6 deletions
+9204
-6
SqlMapper.cs
Dapper NET40/SqlMapper.cs
+117
-4
SqlMapperAsync.cs
Dapper NET45/SqlMapperAsync.cs
+47
-2
Program.cs
Dapper.Contrib.Tests/Program.cs
+2
-0
Tests.cs
DapperTests NET45/Tests.cs
+126
-0
DapperTests NET40.csproj
Tests/DapperTests NET40.csproj
+4
-0
Tests.cs
Tests/Tests.cs
+98
-0
packages.config
Tests/packages.config
+1
-0
FSharp.Core.dll
packages/FSharp.Core.4.0.0/lib/FSharp.Core.dll
+0
-0
FSharp.Core.xml
packages/FSharp.Core.4.0.0/lib/FSharp.Core.xml
+8809
-0
No files found.
Dapper NET40/SqlMapper.cs
View file @
b2952360
...
...
@@ -1711,17 +1711,39 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
{
return
MultiMap
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
cnn
,
sql
,
map
,
param
as
object
,
transaction
,
buffered
,
splitOn
,
commandTimeout
,
commandType
);
}
/// <summary>
/// Perform a multi mapping query with arbitrary input parameters
/// </summary>
/// <typeparam name="TReturn">The return type</typeparam>
/// <param name="cnn"></param>
/// <param name="sql"></param>
/// <param name="types">array of types in the recordset</param>
/// <param name="map"></param>
/// <param name="param"></param>
/// <param name="transaction"></param>
/// <param name="buffered"></param>
/// <param name="splitOn">The Field we should split and read the second object from (default: id)</param>
/// <param name="commandTimeout">Number of seconds before command execution timeout</param>
/// <param name="commandType">Is it a stored proc or a batch?</param>
/// <returns></returns>
public
static
IEnumerable
<
TReturn
>
Query
<
TReturn
>(
this
IDbConnection
cnn
,
string
sql
,
Type
[]
types
,
Func
<
object
[],
TReturn
>
map
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
bool
buffered
=
true
,
string
splitOn
=
"Id"
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
buffered
?
CommandFlags
.
Buffered
:
CommandFlags
.
None
);
var
results
=
MultiMapImpl
<
TReturn
>(
cnn
,
command
,
types
,
map
,
splitOn
,
null
,
null
,
true
);
return
buffered
?
results
.
ToList
()
:
results
;
}
#endif
partial
class
DontMap
{
}
static
IEnumerable
<
TReturn
>
MultiMap
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
this
IDbConnection
cnn
,
string
sql
,
Delegate
map
,
object
param
,
IDbTransaction
transaction
,
bool
buffered
,
string
splitOn
,
int
?
commandTimeout
,
CommandType
?
commandType
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
buffered
?
CommandFlags
.
Buffered
:
CommandFlags
.
None
);
var
results
=
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
cnn
,
command
,
map
,
splitOn
,
null
,
null
);
var
results
=
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
cnn
,
command
,
map
,
splitOn
,
null
,
null
,
true
);
return
buffered
?
results
.
ToList
()
:
results
;
}
static
IEnumerable
<
TReturn
>
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
this
IDbConnection
cnn
,
CommandDefinition
command
,
Delegate
map
,
string
splitOn
,
IDataReader
reader
,
Identity
identity
)
static
IEnumerable
<
TReturn
>
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
this
IDbConnection
cnn
,
CommandDefinition
command
,
Delegate
map
,
string
splitOn
,
IDataReader
reader
,
Identity
identity
,
bool
finalize
)
{
object
param
=
command
.
Parameters
;
identity
=
identity
??
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
typeof
(
TFirst
),
param
==
null
?
null
:
param
.
GetType
(),
new
[]
{
typeof
(
TFirst
),
typeof
(
TSecond
),
typeof
(
TThird
),
typeof
(
TFourth
),
typeof
(
TFifth
),
typeof
(
TSixth
),
typeof
(
TSeventh
)
});
...
...
@@ -1760,7 +1782,82 @@ partial class DontMap { }
{
yield
return
mapIt
(
reader
);
}
command
.
FireOutputCallbacks
();
if
(
finalize
)
{
while
(
reader
.
NextResult
())
{
}
command
.
FireOutputCallbacks
();
}
}
}
finally
{
try
{
if
(
ownedReader
!=
null
)
{
ownedReader
.
Dispose
();
}
}
finally
{
if
(
ownedCommand
!=
null
)
{
ownedCommand
.
Dispose
();
}
if
(
wasClosed
)
cnn
.
Close
();
}
}
}
static
IEnumerable
<
TReturn
>
MultiMapImpl
<
TReturn
>(
this
IDbConnection
cnn
,
CommandDefinition
command
,
Type
[]
types
,
Func
<
object
[],
TReturn
>
map
,
string
splitOn
,
IDataReader
reader
,
Identity
identity
,
bool
finalize
)
{
if
(
types
.
Length
<
1
)
{
throw
new
ArgumentException
(
"you must provide at least one type to deserialize"
);
}
object
param
=
command
.
Parameters
;
identity
=
identity
??
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
types
[
0
],
param
==
null
?
null
:
param
.
GetType
(),
types
);
CacheInfo
cinfo
=
GetCacheInfo
(
identity
,
param
,
command
.
AddToCache
);
IDbCommand
ownedCommand
=
null
;
IDataReader
ownedReader
=
null
;
bool
wasClosed
=
cnn
!=
null
&&
cnn
.
State
==
ConnectionState
.
Closed
;
try
{
if
(
reader
==
null
)
{
ownedCommand
=
command
.
SetupCommand
(
cnn
,
cinfo
.
ParamReader
);
if
(
wasClosed
)
cnn
.
Open
();
ownedReader
=
ownedCommand
.
ExecuteReader
();
reader
=
ownedReader
;
}
DeserializerState
deserializer
=
default
(
DeserializerState
);
Func
<
IDataReader
,
object
>[]
otherDeserializers
=
null
;
int
hash
=
GetColumnHash
(
reader
);
if
((
deserializer
=
cinfo
.
Deserializer
).
Func
==
null
||
(
otherDeserializers
=
cinfo
.
OtherDeserializers
)
==
null
||
hash
!=
deserializer
.
Hash
)
{
var
deserializers
=
GenerateDeserializers
(
types
,
splitOn
,
reader
);
deserializer
=
cinfo
.
Deserializer
=
new
DeserializerState
(
hash
,
deserializers
[
0
]);
otherDeserializers
=
cinfo
.
OtherDeserializers
=
deserializers
.
Skip
(
1
).
ToArray
();
SetQueryCache
(
identity
,
cinfo
);
}
Func
<
IDataReader
,
TReturn
>
mapIt
=
GenerateMapper
(
types
.
Length
,
deserializer
.
Func
,
otherDeserializers
,
map
);
if
(
mapIt
!=
null
)
{
while
(
reader
.
Read
())
{
yield
return
mapIt
(
reader
);
}
if
(
finalize
)
{
while
(
reader
.
NextResult
())
{
}
command
.
FireOutputCallbacks
();
}
}
}
finally
...
...
@@ -1806,6 +1903,22 @@ partial class DontMap { }
}
}
private
static
Func
<
IDataReader
,
TReturn
>
GenerateMapper
<
TReturn
>(
int
length
,
Func
<
IDataReader
,
object
>
deserializer
,
Func
<
IDataReader
,
object
>[]
otherDeserializers
,
Func
<
object
[],
TReturn
>
map
)
{
return
r
=>
{
var
objects
=
new
object
[
length
];
objects
[
0
]
=
deserializer
(
r
);
for
(
var
i
=
1
;
i
<
length
;
++
i
)
{
objects
[
i
]
=
otherDeserializers
[
i
-
1
](
r
);
}
return
map
(
objects
);
};
}
private
static
Func
<
IDataReader
,
object
>[]
GenerateDeserializers
(
Type
[]
types
,
string
splitOn
,
IDataReader
reader
)
{
var
deserializers
=
new
List
<
Func
<
IDataReader
,
object
>>();
...
...
@@ -3888,7 +4001,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
},
gridIndex
);
try
{
foreach
(
var
r
in
SqlMapper
.
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
default
(
CommandDefinition
),
func
,
splitOn
,
reader
,
identity
))
foreach
(
var
r
in
SqlMapper
.
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
default
(
CommandDefinition
),
func
,
splitOn
,
reader
,
identity
,
false
))
{
yield
return
r
;
}
...
...
Dapper NET45/SqlMapperAsync.cs
View file @
b2952360
...
...
@@ -451,7 +451,7 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
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
,
CommandDefinition
.
ForCallback
(
command
.
Parameters
),
map
,
splitOn
,
reader
,
identity
);
var
results
=
MultiMapImpl
<
TFirst
,
TSecond
,
TThird
,
TFourth
,
TFifth
,
TSixth
,
TSeventh
,
TReturn
>(
null
,
CommandDefinition
.
ForCallback
(
command
.
Parameters
),
map
,
splitOn
,
reader
,
identity
,
true
);
return
command
.
Buffered
?
results
.
ToList
()
:
results
;
}
}
finally
...
...
@@ -459,8 +459,53 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
if
(
wasClosed
)
cnn
.
Close
();
}
}
/// <summary>
/// Perform a multi mapping query with arbitrary input parameters
/// </summary>
/// <typeparam name="TReturn">The return type</typeparam>
/// <param name="cnn"></param>
/// <param name="sql"></param>
/// <param name="types">array of types in the recordset</param>
/// <param name="map"></param>
/// <param name="param"></param>
/// <param name="transaction"></param>
/// <param name="buffered"></param>
/// <param name="splitOn">The Field we should split and read the second object from (default: id)</param>
/// <param name="commandTimeout">Number of seconds before command execution timeout</param>
/// <param name="commandType">Is it a stored proc or a batch?</param>
/// <returns></returns>
public
static
Task
<
IEnumerable
<
TReturn
>>
QueryAsync
<
TReturn
>(
this
IDbConnection
cnn
,
string
sql
,
Type
[]
types
,
Func
<
object
[],
TReturn
>
map
,
dynamic
param
=
null
,
IDbTransaction
transaction
=
null
,
bool
buffered
=
true
,
string
splitOn
=
"Id"
,
int
?
commandTimeout
=
null
,
CommandType
?
commandType
=
null
)
{
var
command
=
new
CommandDefinition
(
sql
,
(
object
)
param
,
transaction
,
commandTimeout
,
commandType
,
buffered
?
CommandFlags
.
Buffered
:
CommandFlags
.
None
,
default
(
CancellationToken
));
return
MultiMapAsync
<
TReturn
>(
cnn
,
command
,
types
,
map
,
splitOn
);
}
private
static
async
Task
<
IEnumerable
<
TReturn
>>
MultiMapAsync
<
TReturn
>(
this
IDbConnection
cnn
,
CommandDefinition
command
,
Type
[]
types
,
Func
<
object
[],
TReturn
>
map
,
string
splitOn
)
{
if
(
types
.
Length
<
1
)
{
throw
new
ArgumentException
(
"you must provide at least one type to deserialize"
);
}
object
param
=
command
.
Parameters
;
var
identity
=
new
Identity
(
command
.
CommandText
,
command
.
CommandType
,
cnn
,
types
[
0
],
param
==
null
?
null
:
param
.
GetType
(),
types
);
var
info
=
GetCacheInfo
(
identity
,
param
,
command
.
AddToCache
);
bool
wasClosed
=
cnn
.
State
==
ConnectionState
.
Closed
;
try
{
if
(
wasClosed
)
await
((
DbConnection
)
cnn
).
OpenAsync
().
ConfigureAwait
(
false
);
using
(
var
cmd
=
(
DbCommand
)
command
.
SetupCommand
(
cnn
,
info
.
ParamReader
))
using
(
var
reader
=
await
cmd
.
ExecuteReaderAsync
(
command
.
CancellationToken
).
ConfigureAwait
(
false
))
{
var
results
=
MultiMapImpl
<
TReturn
>(
null
,
default
(
CommandDefinition
),
types
,
map
,
splitOn
,
reader
,
identity
,
true
);
return
command
.
Buffered
?
results
.
ToList
()
:
results
;
}
}
finally
{
if
(
wasClosed
)
cnn
.
Close
();
}
}
private
static
IEnumerable
<
T
>
ExecuteReaderSync
<
T
>(
IDataReader
reader
,
Func
<
IDataReader
,
object
>
func
,
object
parameters
)
private
static
IEnumerable
<
T
>
ExecuteReaderSync
<
T
>(
IDataReader
reader
,
Func
<
IDataReader
,
object
>
func
,
object
parameters
)
{
using
(
reader
)
{
...
...
Dapper.Contrib.Tests/Program.cs
View file @
b2952360
...
...
@@ -46,6 +46,8 @@ private static void RunTests()
method
.
Invoke
(
tester
,
null
);
Console
.
WriteLine
(
" - OK!"
);
}
Console
.
WriteLine
(
"(end of tests; press any key)"
);
Console
.
ReadKey
();
}
...
...
DapperTests NET45/Tests.cs
View file @
b2952360
...
...
@@ -120,6 +120,24 @@ public void TestMultiMapWithSplitAsync()
}
}
public
void
TestMultiMapArbitraryWithSplitAsync
()
{
var
sql
=
@"select 1 as id, 'abc' as name, 2 as id, 'def' as name"
;
using
(
var
connection
=
Program
.
GetOpenConnection
())
{
var
productQuery
=
connection
.
QueryAsync
<
Product
>(
sql
,
new
[]
{
typeof
(
Product
),
typeof
(
Category
)
},
(
objects
)
=>
{
var
prod
=
(
Product
)
objects
[
0
];
prod
.
Category
=
(
Category
)
objects
[
1
];
return
prod
;
});
var
product
=
productQuery
.
Result
.
First
();
// assertions
product
.
Id
.
IsEqualTo
(
1
);
product
.
Name
.
IsEqualTo
(
"abc"
);
product
.
Category
.
Id
.
IsEqualTo
(
2
);
product
.
Category
.
Name
.
IsEqualTo
(
"def"
);
}
}
public
void
TestMultiMapWithSplitClosedConnAsync
()
{
var
sql
=
@"select 1 as id, 'abc' as name, 2 as id, 'def' as name"
;
...
...
@@ -577,5 +595,113 @@ class Address
public
string
Name
{
get
;
set
;
}
public
int
PersonId
{
get
;
set
;
}
}
class
ReviewBoard
{
public
int
Id
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
public
User
User1
{
get
;
set
;
}
public
User
User2
{
get
;
set
;
}
public
User
User3
{
get
;
set
;
}
public
User
User4
{
get
;
set
;
}
public
User
User5
{
get
;
set
;
}
public
User
User6
{
get
;
set
;
}
public
User
User7
{
get
;
set
;
}
public
User
User8
{
get
;
set
;
}
public
User
User9
{
get
;
set
;
}
}
class
User
{
public
int
Id
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
}
public
void
TestMultiMapArbitraryMaps
()
{
// please excuse the trite example, but it is easier to follow than a more real-world one
var
createSql
=
@"
create table #ReviewBoards (Id int, Name varchar(20), User1Id int, User2Id int, User3Id int, User4Id int, User5Id int, User6Id int, User7Id int, User8Id int, User9Id int)
create table #Users (Id int, Name varchar(20))
insert #Users values(1, 'User 1')
insert #Users values(2, 'User 2')
insert #Users values(3, 'User 3')
insert #Users values(4, 'User 4')
insert #Users values(5, 'User 5')
insert #Users values(6, 'User 6')
insert #Users values(7, 'User 7')
insert #Users values(8, 'User 8')
insert #Users values(9, 'User 9')
insert #ReviewBoards values(1, 'Review Board 1', 1, 2, 3, 4, 5, 6, 7, 8, 9)
"
;
using
(
var
connection
=
Program
.
GetOpenConnection
())
{
connection
.
ExecuteAsync
(
createSql
).
Wait
();
try
{
var
sql
=
@"
select
rb.Id, rb.Name,
u1.*, u2.*, u3.*, u4.*, u5.*, u6.*, u7.*, u8.*, u9.*
from #ReviewBoards rb
inner join #Users u1 on u1.Id = rb.User1Id
inner join #Users u2 on u2.Id = rb.User2Id
inner join #Users u3 on u3.Id = rb.User3Id
inner join #Users u4 on u4.Id = rb.User4Id
inner join #Users u5 on u5.Id = rb.User5Id
inner join #Users u6 on u6.Id = rb.User6Id
inner join #Users u7 on u7.Id = rb.User7Id
inner join #Users u8 on u8.Id = rb.User8Id
inner join #Users u9 on u9.Id = rb.User9Id
"
;
var
types
=
new
[]
{
typeof
(
ReviewBoard
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
)
};
Func
<
object
[],
ReviewBoard
>
mapper
=
(
objects
)
=>
{
var
board
=
(
ReviewBoard
)
objects
[
0
];
board
.
User1
=
(
User
)
objects
[
1
];
board
.
User2
=
(
User
)
objects
[
2
];
board
.
User3
=
(
User
)
objects
[
3
];
board
.
User4
=
(
User
)
objects
[
4
];
board
.
User5
=
(
User
)
objects
[
5
];
board
.
User6
=
(
User
)
objects
[
6
];
board
.
User7
=
(
User
)
objects
[
7
];
board
.
User8
=
(
User
)
objects
[
8
];
board
.
User9
=
(
User
)
objects
[
9
];
return
board
;
};
var
data
=
connection
.
QueryAsync
<
ReviewBoard
>(
sql
,
types
,
mapper
).
Result
.
ToList
();
var
p
=
data
.
First
();
p
.
Id
.
IsEqualTo
(
1
);
p
.
Name
.
IsEqualTo
(
"Review Board 1"
);
p
.
User1
.
Id
.
IsEqualTo
(
1
);
p
.
User2
.
Id
.
IsEqualTo
(
2
);
p
.
User3
.
Id
.
IsEqualTo
(
3
);
p
.
User4
.
Id
.
IsEqualTo
(
4
);
p
.
User5
.
Id
.
IsEqualTo
(
5
);
p
.
User6
.
Id
.
IsEqualTo
(
6
);
p
.
User7
.
Id
.
IsEqualTo
(
7
);
p
.
User8
.
Id
.
IsEqualTo
(
8
);
p
.
User9
.
Id
.
IsEqualTo
(
9
);
p
.
User1
.
Name
.
IsEqualTo
(
"User 1"
);
p
.
User2
.
Name
.
IsEqualTo
(
"User 2"
);
p
.
User3
.
Name
.
IsEqualTo
(
"User 3"
);
p
.
User4
.
Name
.
IsEqualTo
(
"User 4"
);
p
.
User5
.
Name
.
IsEqualTo
(
"User 5"
);
p
.
User6
.
Name
.
IsEqualTo
(
"User 6"
);
p
.
User7
.
Name
.
IsEqualTo
(
"User 7"
);
p
.
User8
.
Name
.
IsEqualTo
(
"User 8"
);
p
.
User9
.
Name
.
IsEqualTo
(
"User 9"
);
}
finally
{
connection
.
Execute
(
"drop table #Users drop table #ReviewBoards"
);
}
}
}
}
}
\ No newline at end of file
Tests/DapperTests NET40.csproj
View file @
b2952360
...
...
@@ -47,6 +47,10 @@
<Reference
Include=
"EntityFramework.SqlServer"
>
<HintPath>
..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll
</HintPath>
</Reference>
<Reference
Include=
"FSharp.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
>
<SpecificVersion>
False
</SpecificVersion>
<HintPath>
..\packages\FSharp.Core.4.0.0\lib\FSharp.Core.dll
</HintPath>
</Reference>
<Reference
Include=
"FSharp.PowerPack, Version=2.0.0.0, Culture=neutral, PublicKeyToken=a19089b1c74d0809, processorArchitecture=MSIL"
>
<Private>
True
</Private>
<HintPath>
..\packages\FSPowerPack.Community.2.0.0.0\Lib\Net40\FSharp.PowerPack.dll
</HintPath>
...
...
Tests/Tests.cs
View file @
b2952360
...
...
@@ -785,7 +785,105 @@ public void TestMultiMap()
}
}
class
ReviewBoard
{
public
int
Id
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
public
User
User1
{
get
;
set
;
}
public
User
User2
{
get
;
set
;
}
public
User
User3
{
get
;
set
;
}
public
User
User4
{
get
;
set
;
}
public
User
User5
{
get
;
set
;
}
public
User
User6
{
get
;
set
;
}
public
User
User7
{
get
;
set
;
}
public
User
User8
{
get
;
set
;
}
public
User
User9
{
get
;
set
;
}
}
public
void
TestMultiMapArbitraryMaps
()
{
// please excuse the trite example, but it is easier to follow than a more real-world one
var
createSql
=
@"
create table #ReviewBoards (Id int, Name varchar(20), User1Id int, User2Id int, User3Id int, User4Id int, User5Id int, User6Id int, User7Id int, User8Id int, User9Id int)
create table #Users (Id int, Name varchar(20))
insert #Users values(1, 'User 1')
insert #Users values(2, 'User 2')
insert #Users values(3, 'User 3')
insert #Users values(4, 'User 4')
insert #Users values(5, 'User 5')
insert #Users values(6, 'User 6')
insert #Users values(7, 'User 7')
insert #Users values(8, 'User 8')
insert #Users values(9, 'User 9')
insert #ReviewBoards values(1, 'Review Board 1', 1, 2, 3, 4, 5, 6, 7, 8, 9)
"
;
connection
.
Execute
(
createSql
);
try
{
var
sql
=
@"
select
rb.Id, rb.Name,
u1.*, u2.*, u3.*, u4.*, u5.*, u6.*, u7.*, u8.*, u9.*
from #ReviewBoards rb
inner join #Users u1 on u1.Id = rb.User1Id
inner join #Users u2 on u2.Id = rb.User2Id
inner join #Users u3 on u3.Id = rb.User3Id
inner join #Users u4 on u4.Id = rb.User4Id
inner join #Users u5 on u5.Id = rb.User5Id
inner join #Users u6 on u6.Id = rb.User6Id
inner join #Users u7 on u7.Id = rb.User7Id
inner join #Users u8 on u8.Id = rb.User8Id
inner join #Users u9 on u9.Id = rb.User9Id
"
;
var
types
=
new
[]
{
typeof
(
ReviewBoard
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
),
typeof
(
User
)
};
Func
<
object
[],
ReviewBoard
>
mapper
=
(
objects
)
=>
{
var
board
=
(
ReviewBoard
)
objects
[
0
];
board
.
User1
=
(
User
)
objects
[
1
];
board
.
User2
=
(
User
)
objects
[
2
];
board
.
User3
=
(
User
)
objects
[
3
];
board
.
User4
=
(
User
)
objects
[
4
];
board
.
User5
=
(
User
)
objects
[
5
];
board
.
User6
=
(
User
)
objects
[
6
];
board
.
User7
=
(
User
)
objects
[
7
];
board
.
User8
=
(
User
)
objects
[
8
];
board
.
User9
=
(
User
)
objects
[
9
];
return
board
;
};
var
data
=
connection
.
Query
<
ReviewBoard
>(
sql
,
types
,
mapper
).
ToList
();
var
p
=
data
.
First
();
p
.
Id
.
IsEqualTo
(
1
);
p
.
Name
.
IsEqualTo
(
"Review Board 1"
);
p
.
User1
.
Id
.
IsEqualTo
(
1
);
p
.
User2
.
Id
.
IsEqualTo
(
2
);
p
.
User3
.
Id
.
IsEqualTo
(
3
);
p
.
User4
.
Id
.
IsEqualTo
(
4
);
p
.
User5
.
Id
.
IsEqualTo
(
5
);
p
.
User6
.
Id
.
IsEqualTo
(
6
);
p
.
User7
.
Id
.
IsEqualTo
(
7
);
p
.
User8
.
Id
.
IsEqualTo
(
8
);
p
.
User9
.
Id
.
IsEqualTo
(
9
);
p
.
User1
.
Name
.
IsEqualTo
(
"User 1"
);
p
.
User2
.
Name
.
IsEqualTo
(
"User 2"
);
p
.
User3
.
Name
.
IsEqualTo
(
"User 3"
);
p
.
User4
.
Name
.
IsEqualTo
(
"User 4"
);
p
.
User5
.
Name
.
IsEqualTo
(
"User 5"
);
p
.
User6
.
Name
.
IsEqualTo
(
"User 6"
);
p
.
User7
.
Name
.
IsEqualTo
(
"User 7"
);
p
.
User8
.
Name
.
IsEqualTo
(
"User 8"
);
p
.
User9
.
Name
.
IsEqualTo
(
"User 9"
);
}
finally
{
connection
.
Execute
(
"drop table #Users drop table #ReviewBoards"
);
}
}
public
void
TestMultiMapGridReader
()
{
...
...
Tests/packages.config
View file @
b2952360
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
packages
>
<
package
id
=
"EntityFramework"
version
=
"6.1.0"
targetFramework
=
"net45"
/>
<
package
id
=
"FSharp.Core"
version
=
"4.0.0"
targetFramework
=
"net45"
/>
<
package
id
=
"FSPowerPack.Community"
version
=
"2.0.0.0"
/>
<
package
id
=
"Microsoft.SqlServer.Types"
version
=
"11.0.1"
targetFramework
=
"net45"
/>
<
package
id
=
"Npgsql"
version
=
"2.0.11"
/>
...
...
packages/FSharp.Core.4.0.0/lib/FSharp.Core.dll
0 → 100644
View file @
b2952360
File added
packages/FSharp.Core.4.0.0/lib/FSharp.Core.xml
0 → 100644
View file @
b2952360
This source diff could not be displayed because it is too large. You can
view the blob
instead.
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