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
c4905c57
Commit
c4905c57
authored
May 12, 2015
by
Johan Danforth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New features in Dapper.Contrib
parent
24e55162
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
251 additions
and
38 deletions
+251
-38
TestsAsync.cs
Dapper.Contrib.Tests NET45/TestsAsync.cs
+6
-6
Assert.cs
Dapper.Contrib.Tests/Assert.cs
+8
-0
Tests.cs
Dapper.Contrib.Tests/Tests.cs
+105
-8
Dapper.Contrib.csproj
Dapper.Contrib/Dapper.Contrib.csproj
+3
-0
Readme.md
Dapper.Contrib/Readme.md
+46
-17
SqlMapperExtensions.cs
Dapper.Contrib/SqlMapperExtensions.cs
+83
-7
No files found.
Dapper.Contrib.Tests NET45/TestsAsync.cs
View file @
c4905c57
...
...
@@ -44,7 +44,7 @@ public async Task TestSimpleGetAsync()
{
var
id
=
await
connection
.
InsertAsync
(
new
User
{
Name
=
"Adama"
,
Age
=
10
});
var
user
=
await
connection
.
GetAsync
<
User
>(
id
);
user
.
Id
.
IsEqualTo
((
int
)
id
);
user
.
The
Id
.
IsEqualTo
((
int
)
id
);
user
.
Name
.
IsEqualTo
(
"Adama"
);
await
connection
.
DeleteAsync
(
user
);
}
...
...
@@ -90,7 +90,7 @@ public async Task InsertCheckKeyAsync()
(
await
connection
.
GetAsync
<
IUser
>(
3
)).
IsNull
();
User
user
=
new
User
{
Name
=
"Adamb"
,
Age
=
10
};
int
id
=
(
int
)
await
connection
.
InsertAsync
(
user
);
user
.
Id
.
IsEqualTo
(
id
);
user
.
The
Id
.
IsEqualTo
(
id
);
}
}
...
...
@@ -102,9 +102,9 @@ public async Task BuilderSelectClauseAsync()
var
data
=
new
List
<
User
>();
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
var
nU
=
new
User
{
Age
=
rand
.
Next
(
70
),
Id
=
i
,
Name
=
Guid
.
NewGuid
().
ToString
()
};
var
nU
=
new
User
{
Age
=
rand
.
Next
(
70
),
The
Id
=
i
,
Name
=
Guid
.
NewGuid
().
ToString
()
};
data
.
Add
(
nU
);
nU
.
Id
=
(
int
)
await
connection
.
InsertAsync
<
User
>(
nU
);
nU
.
The
Id
=
(
int
)
await
connection
.
InsertAsync
<
User
>(
nU
);
}
var
builder
=
new
SqlBuilder
();
...
...
@@ -118,8 +118,8 @@ public async Task BuilderSelectClauseAsync()
foreach
(
var
u
in
data
)
{
if
(!
ids
.
Any
(
i
=>
u
.
Id
==
i
))
throw
new
Exception
(
"Missing ids in select"
);
if
(!
users
.
Any
(
a
=>
a
.
Id
==
u
.
Id
&&
a
.
Name
==
u
.
Name
&&
a
.
Age
==
u
.
Age
))
throw
new
Exception
(
"Missing users in select"
);
if
(!
ids
.
Any
(
i
=>
u
.
The
Id
==
i
))
throw
new
Exception
(
"Missing ids in select"
);
if
(!
users
.
Any
(
a
=>
a
.
TheId
==
u
.
The
Id
&&
a
.
Name
==
u
.
Name
&&
a
.
Age
==
u
.
Age
))
throw
new
Exception
(
"Missing users in select"
);
}
}
}
...
...
Dapper.Contrib.Tests/Assert.cs
View file @
c4905c57
...
...
@@ -17,6 +17,14 @@ public static void IsEqualTo<T>(this T obj, T other)
}
}
public
static
void
IsMoreThan
(
this
int
obj
,
int
other
)
{
if
(
obj
<
other
)
{
throw
new
ApplicationException
(
string
.
Format
(
"{0} should be larger than {1}"
,
obj
,
other
));
}
}
public
static
void
IsSequenceEqualTo
<
T
>(
this
IEnumerable
<
T
>
obj
,
IEnumerable
<
T
>
other
)
{
if
(!
obj
.
SequenceEqual
(
other
))
...
...
Dapper.Contrib.Tests/Tests.cs
View file @
c4905c57
using
System.Data
;
using
System
;
using
System.Collections.Generic
;
using
System.Data
;
using
System.Data.SqlServerCe
;
using
System.IO
;
using
System.Linq
;
using
System.Reflection
;
using
System.Transactions
;
using
Dapper.Contrib.Extensions
;
using
System.Collections.Generic
;
using
System
;
namespace
Dapper.Contrib.Tests
{
...
...
@@ -90,10 +89,83 @@ public void TestSimpleGet()
}
}
public
void
InsertList
()
{
const
int
numberOfEntities
=
100
;
var
users
=
new
List
<
User
>();
for
(
var
i
=
0
;
i
<
numberOfEntities
;
i
++)
users
.
Add
(
new
User
{
Name
=
"User "
+
i
,
Age
=
i
});
using
(
var
connection
=
GetOpenConnection
())
{
connection
.
DeleteAll
<
User
>();
var
total
=
connection
.
Insert
(
users
);
total
.
IsEqualTo
(
numberOfEntities
);
users
=
connection
.
Query
<
User
>(
"select * from users"
).
ToList
();
users
.
Count
.
IsEqualTo
(
numberOfEntities
);
}
}
public
void
UpdateList
()
{
const
int
numberOfEntities
=
100
;
var
users
=
new
List
<
User
>();
for
(
var
i
=
0
;
i
<
numberOfEntities
;
i
++)
users
.
Add
(
new
User
{
Name
=
"User "
+
i
,
Age
=
i
});
using
(
var
connection
=
GetOpenConnection
())
{
connection
.
DeleteAll
<
User
>();
var
total
=
connection
.
Insert
(
users
);
total
.
IsEqualTo
(
numberOfEntities
);
users
=
connection
.
Query
<
User
>(
"select * from users"
).
ToList
();
users
.
Count
.
IsEqualTo
(
numberOfEntities
);
foreach
(
var
user
in
users
)
{
user
.
Name
=
user
.
Name
+
" updated"
;
}
connection
.
Update
(
users
);
var
name
=
connection
.
Query
<
User
>(
"select * from users"
).
First
().
Name
;
name
.
Contains
(
"updated"
).
IsTrue
();
}
}
public
void
DeleteList
()
{
const
int
numberOfEntities
=
100
;
var
users
=
new
List
<
User
>();
for
(
var
i
=
0
;
i
<
numberOfEntities
;
i
++)
users
.
Add
(
new
User
{
Name
=
"User "
+
i
,
Age
=
i
});
using
(
var
connection
=
GetOpenConnection
())
{
connection
.
DeleteAll
<
User
>();
var
total
=
connection
.
Insert
(
users
);
total
.
IsEqualTo
(
numberOfEntities
);
users
=
connection
.
Query
<
User
>(
"select * from users"
).
ToList
();
users
.
Count
.
IsEqualTo
(
numberOfEntities
);
var
usersToDelete
=
users
.
Take
(
10
).
ToList
();
connection
.
Delete
(
usersToDelete
);
users
=
connection
.
Query
<
User
>(
"select * from users"
).
ToList
();
users
.
Count
.
IsEqualTo
(
numberOfEntities
-
10
);
}
}
public
void
InsertGetUpdate
()
{
using
(
var
connection
=
GetOpenConnection
())
{
connection
.
DeleteAll
<
User
>();
connection
.
Get
<
User
>(
3
).
IsNull
();
//insert with computed attribute that should be ignored
...
...
@@ -123,9 +195,32 @@ public void InsertGetUpdate()
connection
.
Query
<
User
>(
"select * from Users"
).
Count
().
IsEqualTo
(
0
);
connection
.
Update
(
notrackedUser
).
IsEqualTo
(
false
);
//returns false, user not found
}
}
public
void
GetAll
()
{
const
int
numberOfEntities
=
100
;
var
users
=
new
List
<
User
>();
for
(
var
i
=
0
;
i
<
numberOfEntities
;
i
++)
users
.
Add
(
new
User
{
Name
=
"User "
+
i
,
Age
=
i
});
using
(
var
connection
=
GetOpenConnection
())
{
connection
.
DeleteAll
<
User
>();
var
total
=
connection
.
Insert
(
users
);
total
.
IsEqualTo
(
numberOfEntities
);
users
=
connection
.
GetAll
<
User
>().
ToList
();
users
.
Count
.
IsEqualTo
(
numberOfEntities
);
var
iusers
=
connection
.
GetAll
<
IUser
>().
ToList
();
iusers
.
Count
.
IsEqualTo
(
numberOfEntities
);
}
}
public
void
Transactions
()
{
using
(
var
connection
=
GetOpenConnection
())
...
...
@@ -182,7 +277,7 @@ public void BuilderSelectClause()
{
var
nU
=
new
User
{
Age
=
rand
.
Next
(
70
),
Id
=
i
,
Name
=
Guid
.
NewGuid
().
ToString
()
};
data
.
Add
(
nU
);
nU
.
Id
=
(
int
)
connection
.
Insert
<
User
>
(
nU
);
nU
.
Id
=
(
int
)
connection
.
Insert
(
nU
);
}
var
builder
=
new
SqlBuilder
();
...
...
@@ -212,6 +307,7 @@ public void BuilderTemplateWOComposition()
using
(
var
connection
=
GetOpenConnection
())
{
connection
.
DeleteAll
<
User
>();
connection
.
Insert
(
new
User
{
Age
=
5
,
Name
=
"Testy McTestington"
});
if
(
connection
.
Query
<
int
>(
template
.
RawSql
,
template
.
Parameters
).
Single
()
!=
1
)
...
...
@@ -221,11 +317,12 @@ public void BuilderTemplateWOComposition()
public
void
InsertFieldWithReservedName
()
{
using
(
var
connec
it
on
=
GetOpenConnection
())
using
(
var
connec
ti
on
=
GetOpenConnection
())
{
var
id
=
conneciton
.
Insert
(
new
Result
()
{
Name
=
"Adam"
,
Order
=
1
});
connection
.
DeleteAll
<
User
>();
var
id
=
connection
.
Insert
(
new
Result
()
{
Name
=
"Adam"
,
Order
=
1
});
var
result
=
connec
it
on
.
Get
<
Result
>(
id
);
var
result
=
connec
ti
on
.
Get
<
Result
>(
id
);
result
.
Order
.
IsEqualTo
(
1
);
}
...
...
Dapper.Contrib/Dapper.Contrib.csproj
View file @
c4905c57
...
...
@@ -59,6 +59,9 @@
<Name>
Dapper NET40
</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None
Include=
"Readme.md"
/>
</ItemGroup>
<Import
Project=
"$(MSBuildToolsPath)\Microsoft.CSharp.targets"
/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
...
...
Dapper.Contrib/Readme.md
View file @
c4905c57
...
...
@@ -5,58 +5,87 @@ Features
--------
Dapper.Contrib contains a number of helper methods for inserting, getting, updating and deleting files.
The object you are working with must have a property named Id or a property marked with a
[
Key
]
attribute. As with dapper,
all extension methods assume the connection is already open, they will fail if the connection is closed.
As with dapper, all extension methods assume the connection is already open, they will fail if the
connection is closed. The full list of extension methods in Dapper.Contrib right now are:
Inserts
-------
```
csharp
public
static
long
Insert
<
T
>(
this
IDbConnection
connection
,
T
entityToInsert
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
T
Get
<
T
>(
id
);
IEnumerable
<
T
>
GetAll
<
T
>();
int
Insert
<
T
>(
T
obj
);
int
Insert
<
T
>(
Enumerable
<
T
>
list
);
bool
Update
<
T
>(
T
obj
);
bool
Update
<
T
>(
Enumerable
<
T
>
list
);
bool
Delete
<
T
>(
T
obj
);
bool
Delete
<
T
>(
Enumerable
<
T
>
list
);
bool
DeleteAll
<
T
>();
```
For these extensions to work, the entity in question _MUST_ have a key-property, a property named "id" or decorated with
a
[
Key
]
attribute.
```
csharp
public
class
Car
{
public
int
Id
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
}
connection
.
Insert
(
new
Car
{
Name
=
"Volvo"
});
public
class
User
{
[
Key
]
int
TheId
{
get
;
set
;
}
string
Name
{
get
;
set
;
}
int
Age
{
get
;
set
;
}
}
```
Gets
-------
```
csharp
public
static
T
Get
<
T
>(
this
IDbConnection
connection
,
dynamic
id
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
```
Get one specific entity based on id, or a list of all entities in the table.
```
csharp
var
car
=
connection
.
Get
<
Car
>(
1
);
var
cars
=
connection
.
GetAll
<
Car
>();
```
Update
s
Insert
s
-------
Insert one entity or a list of entities.
```
csharp
public
static
bool
Update
<
T
>(
this
IDbConnection
connection
,
T
entityToUpdate
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
connection
.
Insert
(
new
Car
{
Name
=
"Volvo"
});
connection
.
Insert
(
cars
);
```
Updates
-------
Update one specific entity or update a list of entities.
```
csharp
connection
.
Update
(
new
Car
()
{
Id
=
1
,
Name
=
"Saab"
});
connection
.
Update
(
cars
);
```
Deletes
-------
```
csharp
public
static
bool
Delete
<
T
>(
this
IDbConnection
connection
,
T
entityToDelete
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
public
static
bool
DeleteAll
<
T
>(
this
IDbConnection
connection
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
```
Delete one specific entity, a list of entities, or _ALL_ entities in the table.
```
csharp
connection
.
Delete
(
new
Car
()
{
Id
=
1
});
connection
.
Delete
(
cars
);
connection
.
DeleteAll
<
Car
>();
```
Attributes
Special
Attributes
----------
Dapper.Contrib makes use of some optional attributes:
...
...
Dapper.Contrib/SqlMapperExtensions.cs
View file @
c4905c57
using
System
;
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Data
;
using
System.Linq
;
...
...
@@ -109,6 +110,7 @@ private static bool IsWriteable(PropertyInfo pi)
public
static
T
Get
<
T
>(
this
IDbConnection
connection
,
dynamic
id
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
where
T
:
class
{
var
type
=
typeof
(
T
);
string
sql
;
if
(!
GetQueries
.
TryGetValue
(
type
.
TypeHandle
,
out
sql
))
{
...
...
@@ -122,7 +124,6 @@ private static bool IsWriteable(PropertyInfo pi)
var
name
=
GetTableName
(
type
);
// TODO: pluralizer
// TODO: query information schema and only select fields that are both in information schema and underlying class / interface
sql
=
"select * from "
+
name
+
" where "
+
onlyKey
.
Name
+
" = @id"
;
GetQueries
[
type
.
TypeHandle
]
=
sql
;
...
...
@@ -156,6 +157,58 @@ private static bool IsWriteable(PropertyInfo pi)
}
return
obj
;
}
/// <summary>
/// Returns a list of entites from table "Ts".
/// Id of T must be marked with [Key] attribute.
/// Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension
/// for optimal performance.
/// </summary>
/// <typeparam name="T">Interface or type to create and populate</typeparam>
/// <param name="connection">Open SqlConnection</param>
/// <returns>Entity of T</returns>
public
static
IEnumerable
<
T
>
GetAll
<
T
>(
this
IDbConnection
connection
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
where
T
:
class
{
var
type
=
typeof
(
T
);
var
cacheType
=
typeof
(
List
<
T
>);
string
sql
;
if
(!
GetQueries
.
TryGetValue
(
cacheType
.
TypeHandle
,
out
sql
))
{
var
keys
=
KeyPropertiesCache
(
type
);
if
(
keys
.
Count
()
>
1
)
throw
new
DataException
(
"Get<T> only supports an entity with a single [Key] property"
);
if
(!
keys
.
Any
())
throw
new
DataException
(
"Get<T> only supports en entity with a [Key] property"
);
var
onlyKey
=
keys
.
First
();
var
name
=
GetTableName
(
type
);
// TODO: query information schema and only select fields that are both in information schema and underlying class / interface
sql
=
"select * from "
+
name
;
GetQueries
[
cacheType
.
TypeHandle
]
=
sql
;
}
if
(!
type
.
IsInterface
)
return
connection
.
Query
<
T
>(
sql
,
null
,
transaction
,
commandTimeout
:
commandTimeout
);
var
result
=
connection
.
Query
(
sql
);
var
list
=
new
List
<
T
>();
foreach
(
IDictionary
<
string
,
object
>
res
in
result
)
{
var
obj
=
ProxyGenerator
.
GetInterfaceProxy
<
T
>();
foreach
(
var
property
in
TypePropertiesCache
(
type
))
{
var
val
=
res
[
property
.
Name
];
property
.
SetValue
(
obj
,
val
,
null
);
}
((
IProxy
)
obj
).
IsDirty
=
false
;
//reset change tracking and return
list
.
Add
(
obj
);
}
return
list
;
}
private
static
string
GetTableName
(
Type
type
)
{
string
name
;
...
...
@@ -176,14 +229,23 @@ private static string GetTableName(Type type)
}
/// <summary>
/// Inserts an entity into table "Ts" and returns identity id.
/// Inserts an entity into table "Ts" and returns identity id
or number if inserted rows if inserting a list
.
/// </summary>
/// <param name="connection">Open SqlConnection</param>
/// <param name="entityToInsert">Entity to insert</param>
/// <returns>Identity of inserted entity</returns>
/// <param name="entityToInsert">Entity to insert
, can be list of entities
</param>
/// <returns>Identity of inserted entity
, or number of inserted rows if inserting a list
</returns>
public
static
long
Insert
<
T
>(
this
IDbConnection
connection
,
T
entityToInsert
,
IDbTransaction
transaction
=
null
,
int
?
commandTimeout
=
null
)
where
T
:
class
{
var
isList
=
false
;
var
type
=
typeof
(
T
);
if
(
type
.
IsArray
||
type
.
IsGenericType
)
{
isList
=
true
;
type
=
type
.
GetGenericArguments
()[
0
];
}
var
name
=
GetTableName
(
type
);
var
sbColumnList
=
new
StringBuilder
(
null
);
var
allProperties
=
TypePropertiesCache
(
type
);
...
...
@@ -207,9 +269,17 @@ private static string GetTableName(Type type)
if
(
i
<
allPropertiesExceptKeyAndComputed
.
Count
()
-
1
)
sbParameterList
.
Append
(
", "
);
}
var
adapter
=
GetFormatter
(
connection
);
return
adapter
.
Insert
(
connection
,
transaction
,
commandTimeout
,
name
,
sbColumnList
.
ToString
(),
sbParameterList
.
ToString
(),
keyProperties
,
entityToInsert
);
if
(!
isList
)
//single entity
{
var
adapter
=
GetFormatter
(
connection
);
return
adapter
.
Insert
(
connection
,
transaction
,
commandTimeout
,
name
,
sbColumnList
.
ToString
(),
sbParameterList
.
ToString
(),
keyProperties
,
entityToInsert
);
}
//insert list of entities
var
cmd
=
String
.
Format
(
"insert into {0} ({1}) values ({2})"
,
name
,
sbColumnList
,
sbParameterList
);
return
connection
.
Execute
(
cmd
,
entityToInsert
,
transaction
,
commandTimeout
);
}
/// <summary>
...
...
@@ -229,6 +299,9 @@ private static string GetTableName(Type type)
var
type
=
typeof
(
T
);
if
(
type
.
IsArray
||
type
.
IsGenericType
)
type
=
type
.
GetGenericArguments
()[
0
];
var
keyProperties
=
KeyPropertiesCache
(
type
);
if
(!
keyProperties
.
Any
())
throw
new
ArgumentException
(
"Entity must have at least one [Key] property"
);
...
...
@@ -275,6 +348,9 @@ private static string GetTableName(Type type)
var
type
=
typeof
(
T
);
if
(
type
.
IsArray
||
type
.
IsGenericType
)
type
=
type
.
GetGenericArguments
()[
0
];
var
keyProperties
=
KeyPropertiesCache
(
type
);
if
(!
keyProperties
.
Any
())
throw
new
ArgumentException
(
"Entity must have at least one [Key] property"
);
...
...
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