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
a92c8091
Commit
a92c8091
authored
May 21, 2011
by
johan@JOHAN-DELL-SSD.irm.se
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first version of Get<T>(id), Insert<T>(obj), Update<T>(obj) and Delete<T>(obj)
parent
2b47b1a8
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
867 additions
and
1 deletion
+867
-1
Assert.cs
Dapper.Contrib.Tests/Assert.cs
+53
-0
Dapper.Contrib.Tests.csproj
Dapper.Contrib.Tests/Dapper.Contrib.Tests.csproj
+81
-0
Program.cs
Dapper.Contrib.Tests/Program.cs
+54
-0
AssemblyInfo.cs
Dapper.Contrib.Tests/Properties/AssemblyInfo.cs
+36
-0
Tests.cs
Dapper.Contrib.Tests/Tests.cs
+78
-0
Dapper.Contrib.csproj
Dapper.Contrib/Dapper.Contrib.csproj
+67
-0
ProxyGenerator.cs
Dapper.Contrib/Extensions/ProxyGenerator.cs
+195
-0
SqlMapperExtensions.cs
Dapper.Contrib/Extensions/SqlMapperExtensions.cs
+217
-0
TypeExtension.cs
Dapper.Contrib/Extensions/TypeExtension.cs
+20
-0
AssemblyInfo.cs
Dapper.Contrib/Properties/AssemblyInfo.cs
+36
-0
Dapper.sln
Dapper.sln
+24
-0
SqlMapper.cs
Dapper/SqlMapper.cs
+6
-1
No files found.
Dapper.Contrib.Tests/Assert.cs
0 → 100644
View file @
a92c8091
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
namespace
Dapper.Contrib.Tests
{
/// <summary>
/// Assert extensions borrowed from Sam's code in DapperTests
/// </summary>
static
class
Assert
{
public
static
void
IsEqualTo
<
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
IsSequenceEqualTo
<
T
>(
this
IEnumerable
<
T
>
obj
,
IEnumerable
<
T
>
other
)
{
if
(!
obj
.
SequenceEqual
(
other
))
{
throw
new
ApplicationException
(
string
.
Format
(
"{0} should be equals to {1}"
,
obj
,
other
));
}
}
public
static
void
IsFalse
(
this
bool
b
)
{
if
(
b
)
{
throw
new
ApplicationException
(
"Expected false"
);
}
}
public
static
void
IsTrue
(
this
bool
b
)
{
if
(!
b
)
{
throw
new
ApplicationException
(
"Expected true"
);
}
}
public
static
void
IsNull
(
this
object
obj
)
{
if
(
obj
!=
null
)
{
throw
new
ApplicationException
(
"Expected null"
);
}
}
}
}
\ No newline at end of file
Dapper.Contrib.Tests/Dapper.Contrib.Tests.csproj
0 → 100644
View file @
a92c8091
<?xml version="1.0" encoding="utf-8"?>
<Project
ToolsVersion=
"4.0"
DefaultTargets=
"Build"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<Configuration
Condition=
" '$(Configuration)' == '' "
>
Debug
</Configuration>
<Platform
Condition=
" '$(Platform)' == '' "
>
x86
</Platform>
<ProductVersion>
8.0.30703
</ProductVersion>
<SchemaVersion>
2.0
</SchemaVersion>
<ProjectGuid>
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}
</ProjectGuid>
<OutputType>
Exe
</OutputType>
<AppDesignerFolder>
Properties
</AppDesignerFolder>
<RootNamespace>
Dapper.Contrib.Tests
</RootNamespace>
<AssemblyName>
Dapper.Contrib.Tests
</AssemblyName>
<TargetFrameworkVersion>
v4.0
</TargetFrameworkVersion>
<TargetFrameworkProfile>
Client
</TargetFrameworkProfile>
<FileAlignment>
512
</FileAlignment>
<SccProjectName>
<
Project Location In Database
>
</SccProjectName>
<SccLocalPath>
<
Local Binding Root of Project
>
</SccLocalPath>
<SccAuxPath>
<
Source Control Database
>
</SccAuxPath>
<SccProvider>
Mercurial Source Control Package
</SccProvider>
</PropertyGroup>
<PropertyGroup
Condition=
" '$(Configuration)|$(Platform)' == 'Debug|x86' "
>
<PlatformTarget>
x86
</PlatformTarget>
<DebugSymbols>
true
</DebugSymbols>
<DebugType>
full
</DebugType>
<Optimize>
false
</Optimize>
<OutputPath>
bin\Debug\
</OutputPath>
<DefineConstants>
DEBUG;TRACE
</DefineConstants>
<ErrorReport>
prompt
</ErrorReport>
<WarningLevel>
4
</WarningLevel>
</PropertyGroup>
<PropertyGroup
Condition=
" '$(Configuration)|$(Platform)' == 'Release|x86' "
>
<PlatformTarget>
x86
</PlatformTarget>
<DebugType>
pdbonly
</DebugType>
<Optimize>
true
</Optimize>
<OutputPath>
bin\Release\
</OutputPath>
<DefineConstants>
TRACE
</DefineConstants>
<ErrorReport>
prompt
</ErrorReport>
<WarningLevel>
4
</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference
Include=
"EntityFramework"
>
<HintPath>
Dependencies\EntityFramework.dll
</HintPath>
</Reference>
<Reference
Include=
"System"
/>
<Reference
Include=
"System.ComponentModel.DataAnnotations"
/>
<Reference
Include=
"System.Core"
/>
<Reference
Include=
"System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL"
>
<SpecificVersion>
False
</SpecificVersion>
<HintPath>
Dependencies\System.Data.SqlServerCe.dll
</HintPath>
</Reference>
<Reference
Include=
"System.Xml.Linq"
/>
<Reference
Include=
"System.Data.DataSetExtensions"
/>
<Reference
Include=
"Microsoft.CSharp"
/>
<Reference
Include=
"System.Data"
/>
<Reference
Include=
"System.Xml"
/>
</ItemGroup>
<ItemGroup>
<Compile
Include=
"Assert.cs"
/>
<Compile
Include=
"Program.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Tests.cs"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference
Include=
"..\Dapper.Contrib\Dapper.Contrib.csproj"
>
<Project>
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}
</Project>
<Name>
Dapper.Contrib
</Name>
</ProjectReference>
<ProjectReference
Include=
"..\Dapper\Dapper.csproj"
>
<Project>
{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}
</Project>
<Name>
Dapper
</Name>
</ProjectReference>
</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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
Dapper.Contrib.Tests/Program.cs
0 → 100644
View file @
a92c8091
using
System
;
using
System.Collections.Generic
;
using
System.Data.SqlServerCe
;
using
System.Diagnostics
;
using
System.IO
;
using
System.Linq
;
using
System.Reflection
;
using
System.Text
;
namespace
Dapper.Contrib.Tests
{
class
Program
{
static
void
Main
(
string
[]
args
)
{
Setup
();
RunTests
();
}
private
static
void
Setup
()
{
var
projLoc
=
Assembly
.
GetAssembly
(
typeof
(
Program
)).
Location
;
var
projFolder
=
Path
.
GetDirectoryName
(
projLoc
);
if
(
File
.
Exists
(
projFolder
+
"\\Test.sdf"
))
File
.
Delete
(
projFolder
+
"\\Test.sdf"
);
var
connectionString
=
"Data Source = "
+
projFolder
+
"\\Test.sdf;"
;
var
engine
=
new
SqlCeEngine
(
connectionString
);
engine
.
CreateDatabase
();
using
(
var
connection
=
new
SqlCeConnection
(
connectionString
))
{
connection
.
Open
();
var
sql
=
@"
create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null)
"
;
connection
.
Execute
(
sql
);
}
Console
.
WriteLine
(
"Created database"
);
}
private
static
void
RunTests
()
{
var
tester
=
new
Tests
();
foreach
(
var
method
in
typeof
(
Tests
).
GetMethods
(
BindingFlags
.
Public
|
BindingFlags
.
Instance
|
BindingFlags
.
DeclaredOnly
))
{
Console
.
Write
(
"Running "
+
method
.
Name
);
method
.
Invoke
(
tester
,
null
);
Console
.
WriteLine
(
" - OK!"
);
}
}
}
}
Dapper.Contrib.Tests/Properties/AssemblyInfo.cs
0 → 100644
View file @
a92c8091
using
System.Reflection
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[
assembly
:
AssemblyTitle
(
"Dapper.Contrib.Tests"
)]
[
assembly
:
AssemblyDescription
(
""
)]
[
assembly
:
AssemblyConfiguration
(
""
)]
[
assembly
:
AssemblyCompany
(
"Microsoft"
)]
[
assembly
:
AssemblyProduct
(
"Dapper.Contrib.Tests"
)]
[
assembly
:
AssemblyCopyright
(
"Copyright © Microsoft 2011"
)]
[
assembly
:
AssemblyTrademark
(
""
)]
[
assembly
:
AssemblyCulture
(
""
)]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[
assembly
:
ComVisible
(
false
)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[
assembly
:
Guid
(
"9d5920b6-d6af-41ca-b851-803ac922d933"
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[
assembly
:
AssemblyVersion
(
"1.0.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.0.0.0"
)]
Dapper.Contrib.Tests/Tests.cs
0 → 100644
View file @
a92c8091
using
System
;
using
System.ComponentModel.DataAnnotations
;
using
System.Data
;
using
System.Data.SqlServerCe
;
using
System.Diagnostics
;
using
System.IO
;
using
System.Linq
;
using
System.Reflection
;
using
Dapper.Contrib.Extensions
;
namespace
Dapper.Contrib.Tests
{
public
interface
IUser
{
[
Key
]
int
Id
{
get
;
set
;
}
string
Name
{
get
;
set
;
}
int
Age
{
get
;
set
;
}
}
public
class
User
:
IUser
{
[
Key
]
public
int
Id
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
public
int
Age
{
get
;
set
;
}
}
public
class
Tests
{
private
IDbConnection
GetOpenConnection
()
{
var
projLoc
=
Assembly
.
GetAssembly
(
GetType
()).
Location
;
var
projFolder
=
Path
.
GetDirectoryName
(
projLoc
);
var
connection
=
new
SqlCeConnection
(
"Data Source = "
+
projFolder
+
"\\Test.sdf;"
);
connection
.
Open
();
return
connection
;
}
public
void
Get
()
{
using
(
var
connection
=
GetOpenConnection
())
{
try
{
var
user
=
connection
.
Get
<
User
>(
1
);
Debug
.
Fail
(
"Fail, should have thrown exception"
);
}
catch
(
Exception
)
{
Console
.
WriteLine
(
"ok"
);
}
}
}
public
void
InsertGetUpdate
()
{
using
(
var
connection
=
GetOpenConnection
())
{
var
id
=
connection
.
Insert
(
new
User
{
Name
=
"Adam"
,
Age
=
10
});
id
.
IsEqualTo
(
1
);
var
user
=
connection
.
Get
<
IUser
>(
id
);
user
.
Name
.
IsEqualTo
(
"Adam"
);
connection
.
Update
(
user
).
IsEqualTo
(
false
);
//returns false if not updated, based on tracking
user
.
Name
=
"Bob"
;
connection
.
Update
(
user
).
IsEqualTo
(
true
);
//returns true if updated, based on tracking
user
=
connection
.
Get
<
IUser
>(
id
);
user
.
Name
.
IsEqualTo
(
"Bob"
);
connection
.
Query
<
User
>(
"select * from Users"
).
Count
().
Equals
(
2
);
connection
.
Delete
(
user
).
Equals
(
true
);
connection
.
Query
<
User
>(
"select * from Users"
).
Count
().
Equals
(
1
);
}
}
}
}
Dapper.Contrib/Dapper.Contrib.csproj
0 → 100644
View file @
a92c8091
<?xml version="1.0" encoding="utf-8"?>
<Project
ToolsVersion=
"4.0"
DefaultTargets=
"Build"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<Configuration
Condition=
" '$(Configuration)' == '' "
>
Debug
</Configuration>
<Platform
Condition=
" '$(Platform)' == '' "
>
AnyCPU
</Platform>
<ProductVersion>
8.0.30703
</ProductVersion>
<SchemaVersion>
2.0
</SchemaVersion>
<ProjectGuid>
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}
</ProjectGuid>
<OutputType>
Library
</OutputType>
<AppDesignerFolder>
Properties
</AppDesignerFolder>
<RootNamespace>
Dapper.Contrib
</RootNamespace>
<AssemblyName>
Dapper.Contrib
</AssemblyName>
<TargetFrameworkVersion>
v4.0
</TargetFrameworkVersion>
<FileAlignment>
512
</FileAlignment>
<SccProjectName>
<
Project Location In Database
>
</SccProjectName>
<SccLocalPath>
<
Local Binding Root of Project
>
</SccLocalPath>
<SccAuxPath>
<
Source Control Database
>
</SccAuxPath>
<SccProvider>
Mercurial Source Control Package
</SccProvider>
</PropertyGroup>
<PropertyGroup
Condition=
" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "
>
<DebugSymbols>
true
</DebugSymbols>
<DebugType>
full
</DebugType>
<Optimize>
false
</Optimize>
<OutputPath>
bin\Debug\
</OutputPath>
<DefineConstants>
DEBUG;TRACE
</DefineConstants>
<ErrorReport>
prompt
</ErrorReport>
<WarningLevel>
4
</WarningLevel>
</PropertyGroup>
<PropertyGroup
Condition=
" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "
>
<DebugType>
pdbonly
</DebugType>
<Optimize>
true
</Optimize>
<OutputPath>
bin\Release\
</OutputPath>
<DefineConstants>
TRACE
</DefineConstants>
<ErrorReport>
prompt
</ErrorReport>
<WarningLevel>
4
</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference
Include=
"System"
/>
<Reference
Include=
"System.ComponentModel.DataAnnotations"
/>
<Reference
Include=
"System.Core"
/>
<Reference
Include=
"System.Xml.Linq"
/>
<Reference
Include=
"System.Data.DataSetExtensions"
/>
<Reference
Include=
"Microsoft.CSharp"
/>
<Reference
Include=
"System.Data"
/>
<Reference
Include=
"System.Xml"
/>
</ItemGroup>
<ItemGroup>
<Compile
Include=
"Extensions\ProxyGenerator.cs"
/>
<Compile
Include=
"Extensions\SqlMapperExtensions.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Extensions\TypeExtension.cs"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference
Include=
"..\Dapper\Dapper.csproj"
>
<Project>
{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}
</Project>
<Name>
Dapper
</Name>
</ProjectReference>
</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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
Dapper.Contrib/Extensions/ProxyGenerator.cs
0 → 100644
View file @
a92c8091
using
System
;
using
System.Collections.Generic
;
using
System.ComponentModel.DataAnnotations
;
using
System.Linq
;
using
System.Reflection
;
using
System.Reflection.Emit
;
using
System.Text
;
using
System.Threading
;
namespace
Dapper.Contrib.Extensions
{
//TODO: Try hiding this interface
public
interface
IProxy
{
bool
IsDirty
{
get
;
set
;
}
}
class
ProxyGenerator
{
private
static
readonly
Dictionary
<
Type
,
object
>
TypeCache
=
new
Dictionary
<
Type
,
object
>();
private
static
AssemblyBuilder
GetAsmBuilder
(
string
name
)
{
var
assemblyBuilder
=
Thread
.
GetDomain
().
DefineDynamicAssembly
(
new
AssemblyName
{
Name
=
name
},
AssemblyBuilderAccess
.
Run
);
//NOTE: to save, use RunAndSave
return
assemblyBuilder
;
}
public
static
T
GetInterfaceProxy
<
T
>()
{
Type
typeOfT
=
typeof
(
T
);
if
(
TypeCache
.
ContainsKey
(
typeOfT
))
{
return
(
T
)
TypeCache
[
typeOfT
];
}
var
assemblyBuilder
=
GetAsmBuilder
(
typeOfT
.
Name
);
var
moduleBuilder
=
assemblyBuilder
.
DefineDynamicModule
(
"SqlMapperExtensions."
+
typeOfT
.
Name
);
//NOTE: to save, add "asdasd.dll" parameter
var
interfaceType
=
typeof
(
IProxy
);
var
typeBuilder
=
moduleBuilder
.
DefineType
(
typeOfT
.
Name
+
"_"
+
Guid
.
NewGuid
(),
TypeAttributes
.
Public
|
TypeAttributes
.
Class
);
typeBuilder
.
AddInterfaceImplementation
(
typeOfT
);
typeBuilder
.
AddInterfaceImplementation
(
interfaceType
);
//create our _isDirty field, which implements IProxy
var
setIsDirtyMethod
=
CreateIsDirtyProperty
(
typeBuilder
);
// Generate a field for each property, which implements the T
foreach
(
var
property
in
typeof
(
T
).
GetProperties
())
{
var
isId
=
property
.
GetCustomAttributes
(
true
).
Any
(
a
=>
a
is
KeyAttribute
);
CreateProperty
<
T
>(
typeBuilder
,
property
.
Name
,
property
.
PropertyType
,
setIsDirtyMethod
,
isId
);
}
var
generatedType
=
typeBuilder
.
CreateType
();
//assemblyBuilder.Save(name + ".dll"); //NOTE: to save, uncomment
var
generatedObject
=
Activator
.
CreateInstance
(
generatedType
);
TypeCache
.
Add
(
typeOfT
,
generatedObject
);
return
(
T
)
generatedObject
;
}
private
static
MethodInfo
CreateIsDirtyProperty
(
TypeBuilder
typeBuilder
)
{
Type
propType
=
typeof
(
bool
);
FieldBuilder
field
=
typeBuilder
.
DefineField
(
"_"
+
"IsDirty"
,
propType
,
FieldAttributes
.
Private
);
// Generate a public property
PropertyBuilder
property
=
typeBuilder
.
DefineProperty
(
"IsDirty"
,
PropertyAttributes
.
None
,
propType
,
new
Type
[]
{
propType
});
// The property set and property get methods require a special set of attributes:
MethodAttributes
GetSetAttr
=
MethodAttributes
.
Public
|
MethodAttributes
.
NewSlot
|
MethodAttributes
.
SpecialName
|
MethodAttributes
.
Final
|
MethodAttributes
.
Virtual
|
MethodAttributes
.
HideBySig
;
// Define the "get" accessor method for current private field.
MethodBuilder
currGetPropMthdBldr
=
typeBuilder
.
DefineMethod
(
"get_"
+
"IsDirty"
,
GetSetAttr
,
propType
,
Type
.
EmptyTypes
);
// Intermediate Language stuff...
ILGenerator
currGetIL
=
currGetPropMthdBldr
.
GetILGenerator
();
currGetIL
.
Emit
(
OpCodes
.
Ldarg_0
);
currGetIL
.
Emit
(
OpCodes
.
Ldfld
,
field
);
currGetIL
.
Emit
(
OpCodes
.
Ret
);
// Define the "set" accessor method for current private field.
MethodBuilder
currSetPropMthdBldr
=
typeBuilder
.
DefineMethod
(
"set_"
+
"IsDirty"
,
GetSetAttr
,
null
,
new
Type
[]
{
propType
});
// Again some Intermediate Language stuff...
ILGenerator
currSetIL
=
currSetPropMthdBldr
.
GetILGenerator
();
currSetIL
.
Emit
(
OpCodes
.
Ldarg_0
);
currSetIL
.
Emit
(
OpCodes
.
Ldarg_1
);
currSetIL
.
Emit
(
OpCodes
.
Stfld
,
field
);
currSetIL
.
Emit
(
OpCodes
.
Ret
);
// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.
property
.
SetGetMethod
(
currGetPropMthdBldr
);
property
.
SetSetMethod
(
currSetPropMthdBldr
);
MethodInfo
getMethod
=
typeof
(
IProxy
).
GetMethod
(
"get_"
+
"IsDirty"
);
MethodInfo
setMethod
=
typeof
(
IProxy
).
GetMethod
(
"set_"
+
"IsDirty"
);
typeBuilder
.
DefineMethodOverride
(
currGetPropMthdBldr
,
getMethod
);
typeBuilder
.
DefineMethodOverride
(
currSetPropMthdBldr
,
setMethod
);
return
currSetPropMthdBldr
;
}
private
static
void
CreateProperty
<
T
>(
TypeBuilder
typeBuilder
,
string
propertyName
,
Type
propType
,
MethodInfo
setIsDirtyMethod
,
bool
isIdentity
)
{
FieldBuilder
field
=
typeBuilder
.
DefineField
(
"_"
+
propertyName
,
propType
,
FieldAttributes
.
Private
);
// Generate a public property
PropertyBuilder
property
=
typeBuilder
.
DefineProperty
(
propertyName
,
PropertyAttributes
.
None
,
propType
,
new
Type
[]
{
propType
});
// The property set and property get methods require a special set of attributes:
MethodAttributes
GetSetAttr
=
MethodAttributes
.
Public
|
MethodAttributes
.
Virtual
|
MethodAttributes
.
HideBySig
;
// Define the "get" accessor method for current private field.
MethodBuilder
currGetPropMthdBldr
=
typeBuilder
.
DefineMethod
(
"get_"
+
propertyName
,
GetSetAttr
,
propType
,
Type
.
EmptyTypes
);
// Intermediate Language stuff...
ILGenerator
currGetIL
=
currGetPropMthdBldr
.
GetILGenerator
();
currGetIL
.
Emit
(
OpCodes
.
Ldarg_0
);
currGetIL
.
Emit
(
OpCodes
.
Ldfld
,
field
);
currGetIL
.
Emit
(
OpCodes
.
Ret
);
// Define the "set" accessor method for current private field.
MethodBuilder
currSetPropMthdBldr
=
typeBuilder
.
DefineMethod
(
"set_"
+
propertyName
,
GetSetAttr
,
null
,
new
Type
[]
{
propType
});
// Again some Intermediate Language stuff...
ILGenerator
currSetIL
=
currSetPropMthdBldr
.
GetILGenerator
();
currSetIL
.
Emit
(
OpCodes
.
Ldarg_0
);
currSetIL
.
Emit
(
OpCodes
.
Ldarg_1
);
currSetIL
.
Emit
(
OpCodes
.
Stfld
,
field
);
currSetIL
.
Emit
(
OpCodes
.
Ldarg_0
);
currSetIL
.
Emit
(
OpCodes
.
Ldc_I4_1
);
currSetIL
.
Emit
(
OpCodes
.
Call
,
setIsDirtyMethod
);
currSetIL
.
Emit
(
OpCodes
.
Ret
);
if
(
isIdentity
)
{
Type
keyAttribute
=
typeof
(
KeyAttribute
);
// Create a Constructorinfo object for attribute 'MyAttribute1'.
ConstructorInfo
myConstructorInfo
=
keyAttribute
.
GetConstructor
(
new
Type
[]
{
});
// Create the CustomAttribute instance of attribute of type 'MyAttribute1'.
CustomAttributeBuilder
attributeBuilder
=
new
CustomAttributeBuilder
(
myConstructorInfo
,
new
object
[]
{
});
property
.
SetCustomAttribute
(
attributeBuilder
);
}
// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.
property
.
SetGetMethod
(
currGetPropMthdBldr
);
property
.
SetSetMethod
(
currSetPropMthdBldr
);
MethodInfo
getMethod
=
typeof
(
T
).
GetMethod
(
"get_"
+
propertyName
);
MethodInfo
setMethod
=
typeof
(
T
).
GetMethod
(
"set_"
+
propertyName
);
typeBuilder
.
DefineMethodOverride
(
currGetPropMthdBldr
,
getMethod
);
typeBuilder
.
DefineMethodOverride
(
currSetPropMthdBldr
,
setMethod
);
}
}
}
Dapper.Contrib/Extensions/SqlMapperExtensions.cs
0 → 100644
View file @
a92c8091
using
System
;
using
System.Collections.Generic
;
using
System.ComponentModel.DataAnnotations
;
using
System.Data
;
using
System.Linq
;
using
System.Reflection
;
using
System.Text
;
namespace
Dapper.Contrib.Extensions
{
public
static
class
SqlMapperExtensions
{
private
static
readonly
Dictionary
<
Type
,
IEnumerable
<
PropertyInfo
>>
KeyProperties
=
new
Dictionary
<
Type
,
IEnumerable
<
PropertyInfo
>>();
private
static
readonly
Dictionary
<
Type
,
IEnumerable
<
PropertyInfo
>>
TypeProperties
=
new
Dictionary
<
Type
,
IEnumerable
<
PropertyInfo
>>();
private
static
IEnumerable
<
PropertyInfo
>
KeyPropertiesCache
(
Type
type
)
{
if
(
KeyProperties
.
ContainsKey
(
type
))
{
return
KeyProperties
[
type
];
}
var
allProperties
=
TypePropertiesCache
(
type
);
var
keyProperties
=
allProperties
.
Where
(
p
=>
p
.
GetCustomAttributes
(
true
).
Any
(
a
=>
a
is
KeyAttribute
));
KeyProperties
.
Add
(
type
,
keyProperties
);
return
keyProperties
;
}
private
static
IEnumerable
<
PropertyInfo
>
TypePropertiesCache
(
Type
type
)
{
if
(
TypeProperties
.
ContainsKey
(
type
))
{
return
TypeProperties
[
type
];
}
var
properties
=
type
.
GetProperties
();
TypeProperties
.
Add
(
type
,
properties
);
return
properties
;
}
/// <summary>
/// Returns a single entity by a single id from table "Ts". T must be of interface type.
/// Id must be marked with [Key] attribute.
/// Created entity is tracked/intercepted for changes and used by the Update() extension.
/// </summary>
/// <typeparam name="T">Interface type to create and populate</typeparam>
/// <param name="connection">Open SqlConnection</param>
/// <param name="id">Id of the entity to get, must be marked with [Key] attribute</param>
/// <returns>Entity of T</returns>
public
static
T
Get
<
T
>(
this
IDbConnection
connection
,
object
id
)
{
var
type
=
typeof
(
T
);
if
(!
type
.
IsInterface
)
throw
new
DataException
(
"This version of Get<T>() only supports interfaces."
);
var
keys
=
KeyPropertiesCache
(
type
);
if
(
keys
.
Count
()
>
1
)
throw
new
DataException
(
"Get<T> only supports an entity with a single [Key] property"
);
if
(
keys
.
Count
()
==
0
)
throw
new
DataException
(
"Get<T> only supports en entity with a [Key] property"
);
var
onlyKey
=
keys
.
First
();
var
name
=
type
.
Name
;
if
(
type
.
IsInterface
&&
name
.
StartsWith
(
"I"
))
name
=
name
.
Substring
(
1
);
var
sql
=
"select * from "
+
name
+
"s where "
+
onlyKey
.
Name
+
" = @"
+
onlyKey
.
Name
;
var
dynParms
=
new
DynamicParameters
();
dynParms
.
Add
(
"@"
+
onlyKey
.
Name
,
id
);
if
(
type
.
IsInterface
)
{
var
proxy
=
ProxyGenerator
.
GetInterfaceProxy
<
T
>();
var
res
=
connection
.
Query
(
sql
,
dynParms
).
FirstOrDefault
()
as
SqlMapper
.
FastExpando
;
foreach
(
var
property
in
TypePropertiesCache
(
type
))
{
var
val
=
res
.
GetProperty
(
property
.
Name
);
property
.
SetValue
(
proxy
,
val
,
null
);
}
((
IProxy
)
proxy
).
IsDirty
=
false
;
//reset change tracking and return
return
proxy
;
}
else
//for future support, will never be called now...
{
var
res
=
connection
.
Query
<
T
>(
sql
,
dynParms
);
return
res
.
FirstOrDefault
();
}
}
/// <summary>
/// Inserts an entity into table "Ts" and returns identity id.
/// </summary>
/// <param name="connection">Open SqlConnection</param>
/// <param name="entityToInsert">Entity to insert</param>
/// <returns>Identity of inserted entity</returns>
public
static
long
Insert
<
T
>(
this
IDbConnection
connection
,
T
entityToInsert
)
{
var
tx
=
connection
.
BeginTransaction
();
var
name
=
entityToInsert
.
GetType
().
Name
;
var
sb
=
new
StringBuilder
(
null
);
sb
.
AppendFormat
(
"insert into {0}s ("
,
name
);
var
allProperties
=
TypePropertiesCache
(
typeof
(
T
));
var
keyProperties
=
KeyPropertiesCache
(
typeof
(
T
));
for
(
var
i
=
0
;
i
<
allProperties
.
Count
();
i
++)
{
var
property
=
allProperties
.
ElementAt
(
i
);
if
(
keyProperties
.
Contains
(
property
))
continue
;
sb
.
Append
(
property
.
Name
);
if
(
i
<
allProperties
.
Count
()
-
1
)
sb
.
Append
(
", "
);
}
sb
.
Append
(
") values ("
);
for
(
var
i
=
0
;
i
<
allProperties
.
Count
();
i
++)
{
var
property
=
allProperties
.
ElementAt
(
i
);
if
(
keyProperties
.
Contains
(
property
))
continue
;
sb
.
AppendFormat
(
"@{0}"
,
property
.
Name
);
if
(
i
<
allProperties
.
Count
()
-
1
)
sb
.
Append
(
", "
);
}
sb
.
Append
(
") "
);
connection
.
Execute
(
sb
.
ToString
(),
entityToInsert
);
//NOTE: would prefer to use IDENT_CURRENT('tablename') or IDENT_SCOPE but these are not available on SQLCE
var
r
=
connection
.
Query
(
"select @@IDENTITY id"
);
tx
.
Commit
();
return
(
int
)
r
.
First
().
id
;
}
/// <summary>
/// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
/// </summary>
/// <typeparam name="T">Type to be updated</typeparam>
/// <param name="connection">Open SqlConnection</param>
/// <param name="entityToUpdate">Entity to be updated</param>
/// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
public
static
bool
Update
<
T
>(
this
IDbConnection
connection
,
T
entityToUpdate
)
{
var
proxy
=
((
IProxy
)
entityToUpdate
);
if
(
proxy
!=
null
)
{
if
(!
proxy
.
IsDirty
)
return
false
;
}
var
type
=
typeof
(
T
);
var
keyProperties
=
KeyPropertiesCache
(
type
);
if
(
keyProperties
.
Count
()
==
0
)
throw
new
ArgumentException
(
"Entity must have at least one [Key] property"
);
var
name
=
type
.
Name
;
if
(
type
.
IsInterface
&&
name
.
StartsWith
(
"I"
))
name
=
name
.
Substring
(
1
);
var
sb
=
new
StringBuilder
();
sb
.
AppendFormat
(
"update {0}s set "
,
name
);
var
allProperties
=
TypePropertiesCache
(
type
);
var
nonIdProps
=
allProperties
.
Where
(
a
=>
!
keyProperties
.
Contains
(
a
));
for
(
var
i
=
0
;
i
<
nonIdProps
.
Count
();
i
++)
{
var
property
=
nonIdProps
.
ElementAt
(
i
);
sb
.
AppendFormat
(
"{0} = @{1}"
,
property
.
Name
,
property
.
Name
);
if
(
i
<
nonIdProps
.
Count
()
-
1
)
sb
.
AppendFormat
(
", "
);
}
sb
.
Append
(
" where "
);
for
(
var
i
=
0
;
i
<
keyProperties
.
Count
();
i
++)
{
var
property
=
keyProperties
.
ElementAt
(
i
);
sb
.
AppendFormat
(
"{0} = @{1}"
,
property
.
Name
,
property
.
Name
);
if
(
i
<
keyProperties
.
Count
()
-
1
)
sb
.
AppendFormat
(
" and "
);
}
var
updated
=
connection
.
Execute
(
sb
.
ToString
(),
entityToUpdate
);
return
updated
>
0
;
}
/// <summary>
/// Delete entity in table "Ts".
/// </summary>
/// <typeparam name="T">Type of entity</typeparam>
/// <param name="connection">Open SqlConnection</param>
/// <param name="entityToDelete">Entity to delete</param>
/// <returns>true if deleted, false if not found</returns>
public
static
bool
Delete
<
T
>(
this
IDbConnection
connection
,
T
entityToDelete
)
{
var
type
=
typeof
(
T
);
var
keyProperties
=
KeyPropertiesCache
(
type
);
if
(
keyProperties
.
Count
()
==
0
)
throw
new
ArgumentException
(
"Entity must have at least one [Key] property"
);
var
name
=
type
.
Name
;
if
(
type
.
IsInterface
&&
name
.
StartsWith
(
"I"
))
name
=
name
.
Substring
(
1
);
var
sb
=
new
StringBuilder
();
sb
.
AppendFormat
(
"delete from {0}s where "
,
name
);
for
(
var
i
=
0
;
i
<
keyProperties
.
Count
();
i
++)
{
var
property
=
keyProperties
.
ElementAt
(
i
);
sb
.
AppendFormat
(
"{0} = @{1}"
,
property
.
Name
,
property
.
Name
);
if
(
i
<
keyProperties
.
Count
()
-
1
)
sb
.
AppendFormat
(
" and "
);
}
var
deleted
=
connection
.
Execute
(
sb
.
ToString
(),
entityToDelete
);
return
deleted
>
0
;
}
}
}
Dapper.Contrib/Extensions/TypeExtension.cs
0 → 100644
View file @
a92c8091
using
System
;
using
System.Linq
;
using
System.Runtime.CompilerServices
;
namespace
Dapper.Contrib
{
public
static
class
TypeExtension
{
public
static
Boolean
IsAnonymousType
(
this
Type
type
)
{
if
(
type
==
null
)
return
false
;
var
hasCompilerGeneratedAttribute
=
type
.
GetCustomAttributes
(
typeof
(
CompilerGeneratedAttribute
),
false
).
Count
()
>
0
;
var
nameContainsAnonymousType
=
type
.
FullName
.
Contains
(
"AnonymousType"
);
var
isAnonymousType
=
hasCompilerGeneratedAttribute
&&
nameContainsAnonymousType
;
return
isAnonymousType
;
}
}
}
\ No newline at end of file
Dapper.Contrib/Properties/AssemblyInfo.cs
0 → 100644
View file @
a92c8091
using
System.Reflection
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[
assembly
:
AssemblyTitle
(
"Dapper.Contrib"
)]
[
assembly
:
AssemblyDescription
(
""
)]
[
assembly
:
AssemblyConfiguration
(
""
)]
[
assembly
:
AssemblyCompany
(
"Microsoft"
)]
[
assembly
:
AssemblyProduct
(
"Dapper.Contrib"
)]
[
assembly
:
AssemblyCopyright
(
"Copyright © Microsoft 2011"
)]
[
assembly
:
AssemblyTrademark
(
""
)]
[
assembly
:
AssemblyCulture
(
""
)]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[
assembly
:
ComVisible
(
false
)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[
assembly
:
Guid
(
"6dde1c15-4e92-45e7-93fc-88778d15ff31"
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[
assembly
:
AssemblyVersion
(
"1.0.0.0"
)]
[
assembly
:
AssemblyFileVersion
(
"1.0.0.0"
)]
Dapper.sln
View file @
a92c8091
...
...
@@ -5,6 +5,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper", "Dapper\Dapper.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DapperTests", "Tests\DapperTests.csproj", "{A2A80512-11F4-4028-A995-505463632C84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Contrib", "Dapper.Contrib\Dapper.Contrib.csproj", "{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Contrib.Tests", "Dapper.Contrib.Tests\Dapper.Contrib.Tests.csproj", "{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
...
...
@@ -35,6 +39,26 @@ Global
{A2A80512-11F4-4028-A995-505463632C84}.Release|Mixed Platforms.Build.0 = Release|x86
{A2A80512-11F4-4028-A995-505463632C84}.Release|x86.ActiveCfg = Release|x86
{A2A80512-11F4-4028-A995-505463632C84}.Release|x86.Build.0 = Release|x86
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Debug|x86.ActiveCfg = Debug|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Release|Any CPU.Build.0 = Release|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}.Release|x86.ActiveCfg = Release|Any CPU
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Debug|Any CPU.ActiveCfg = Debug|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Debug|Mixed Platforms.Build.0 = Debug|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Debug|x86.ActiveCfg = Debug|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Debug|x86.Build.0 = Debug|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Release|Any CPU.ActiveCfg = Release|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Release|Mixed Platforms.ActiveCfg = Release|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Release|Mixed Platforms.Build.0 = Release|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Release|x86.ActiveCfg = Release|x86
{A4F4A06E-D179-4251-A232-AEF4CE9AD9B5}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
...
...
Dapper/SqlMapper.cs
View file @
a92c8091
...
...
@@ -399,7 +399,7 @@ private static CacheInfo GetCacheInfo(object param, Identity identity)
}
p
rivate
class
FastExpando
:
DynamicObject
p
ublic
class
FastExpando
:
DynamicObject
{
IDictionary
<
string
,
object
>
data
;
...
...
@@ -418,6 +418,11 @@ public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return
data
.
TryGetValue
(
binder
.
Name
,
out
result
);
}
public
object
GetProperty
(
string
name
)
{
return
data
[
name
];
}
}
private
static
Func
<
IDataReader
,
T
>
GetDynamicDeserializer
<
T
>(
IDataRecord
reader
,
int
startBound
=
0
,
int
length
=
-
1
,
bool
returnNullIfFirstMissing
=
false
)
...
...
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