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
3fe88fc1
Commit
3fe88fc1
authored
Aug 30, 2019
by
mgravell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add Dapper.ProviderTools lib
parent
b5352775
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
341 additions
and
6 deletions
+341
-6
BulkCopy.cs
Dapper.ProviderTools/BulkCopy.cs
+122
-0
Dapper.ProviderTools.csproj
Dapper.ProviderTools/Dapper.ProviderTools.csproj
+20
-0
DbExceptionExtensions.cs
Dapper.ProviderTools/DbExceptionExtensions.cs
+64
-0
DynamicBulkCopy.cs
Dapper.ProviderTools/Internal/DynamicBulkCopy.cs
+56
-0
Dapper.Tests.csproj
Dapper.Tests/Dapper.Tests.csproj
+5
-6
ProviderTests.cs
Dapper.Tests/ProviderTests.cs
+67
-0
Dapper.sln
Dapper.sln
+7
-0
No files found.
Dapper.ProviderTools/BulkCopy.cs
0 → 100644
View file @
3fe88fc1
using
System
;
using
System.Collections.Concurrent
;
using
System.Data
;
using
System.Data.Common
;
using
System.Linq.Expressions
;
using
System.Text.RegularExpressions
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Dapper.ProviderTools.Internal
;
namespace
Dapper.ProviderTools
{
/// <summary>
/// Provides provider-agnostic access to bulk-copy services
/// </summary>
public
abstract
class
BulkCopy
:
IDisposable
{
/// <summary>
/// Attempt to create a BulkCopy instance for the connection provided
/// </summary>
public
static
BulkCopy
?
TryCreate
(
DbConnection
connection
)
{
if
(
connection
==
null
)
return
null
;
var
type
=
connection
.
GetType
();
if
(!
s_bcpFactory
.
TryGetValue
(
type
,
out
var
func
))
{
s_bcpFactory
[
type
]
=
func
=
CreateBcpFactory
(
type
);
}
var
obj
=
func
?.
Invoke
(
connection
);
return
DynamicBulkCopy
.
Create
(
obj
);
}
/// <summary>
/// Provide an external registration for a given connection type
/// </summary>
public
static
void
Register
(
Type
type
,
Func
<
DbConnection
,
object
>?
factory
)
=>
s_bcpFactory
[
type
]
=
factory
;
private
static
readonly
ConcurrentDictionary
<
Type
,
Func
<
DbConnection
,
object
>?>
s_bcpFactory
=
new
ConcurrentDictionary
<
Type
,
Func
<
DbConnection
,
object
>?>();
internal
static
Func
<
DbConnection
,
object
>?
CreateBcpFactory
(
Type
connectionType
)
{
try
{
var
match
=
Regex
.
Match
(
connectionType
.
Name
,
"^(.+)Connection$"
);
if
(
match
.
Success
)
{
var
prefix
=
match
.
Groups
[
1
].
Value
;
var
bcpType
=
connectionType
.
Assembly
.
GetType
(
$"
{
connectionType
.
Namespace
}
.
{
prefix
}
BulkCopy"
);
if
(
bcpType
!=
null
)
{
var
ctor
=
bcpType
.
GetConstructor
(
new
[]
{
connectionType
});
if
(
ctor
==
null
)
return
null
;
var
p
=
Expression
.
Parameter
(
typeof
(
DbConnection
),
"conn"
);
var
body
=
Expression
.
New
(
ctor
,
Expression
.
Convert
(
p
,
connectionType
));
return
Expression
.
Lambda
<
Func
<
DbConnection
,
object
>>(
body
,
p
).
Compile
();
}
}
}
catch
{
}
return
null
;
}
/// <summary>
/// Name of the destination table on the server.
/// </summary>
public
abstract
string
DestinationTableName
{
get
;
set
;
}
/// <summary>
/// Write a set of data to the server
/// </summary>
public
abstract
void
WriteToServer
(
DataTable
source
);
/// <summary>
/// Write a set of data to the server
/// </summary>
public
abstract
void
WriteToServer
(
IDataReader
source
);
/// <summary>
/// Write a set of data to the server
/// </summary>
public
abstract
Task
WriteToServerAsync
(
DbDataReader
source
,
CancellationToken
cancellationToken
);
/// <summary>
/// Write a set of data to the server
/// </summary>
public
abstract
Task
WriteToServerAsync
(
DataTable
source
,
CancellationToken
cancellationToken
);
/// <summary>
/// Add a mapping between two columns by name
/// </summary>
public
abstract
void
AddColumnMapping
(
string
sourceColumn
,
string
destinationColumn
);
/// <summary>
/// Add a mapping between two columns by position
/// </summary>
public
abstract
void
AddColumnMapping
(
int
sourceColumn
,
int
destinationColumn
);
/// <summary>
/// The underlying untyped object providing the bulk-copy service
/// </summary>
public
abstract
object
Wrapped
{
get
;
}
/// <summary>
/// Enables or disables streaming from a data-reader
/// </summary>
public
bool
EnableStreaming
{
get
;
set
;
}
/// <summary>
/// Number of rows in each batch
/// </summary>
public
int
BatchSize
{
get
;
set
;
}
/// <summary>
/// Number of seconds for the operation to complete before it times out.
/// </summary>
public
int
BulkCopyTimeout
{
get
;
set
;
}
/// <summary>
/// Release any resources associated with this instance
/// </summary>
public
void
Dispose
()
=>
Dispose
(
true
);
/// <summary>
/// Release any resources associated with this instance
/// </summary>
protected
abstract
void
Dispose
(
bool
disposing
);
}
}
Dapper.ProviderTools/Dapper.ProviderTools.csproj
0 → 100644
View file @
3fe88fc1
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Dapper.ProviderTools</AssemblyName>
<PackageTags>orm;sql;micro-orm</PackageTags>
<Title>Dapper Provider Tools</Title>
<Description>Provider-agnostic ADO.NET helper utilities</Description>
<Authors>Marc Gravell</Authors>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<SignAssembly>true</SignAssembly>
<Nullable>enable</Nullable>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
</ItemGroup>
</Project>
Dapper.ProviderTools/DbExceptionExtensions.cs
0 → 100644
View file @
3fe88fc1
using
System
;
using
System.Collections.Concurrent
;
using
System.Data.Common
;
using
System.Linq.Expressions
;
using
System.Reflection
;
namespace
Dapper.ProviderTools
{
/// <summary>
/// Helper utilties for working with database exceptions
/// </summary>
public
static
class
DbExceptionExtensions
{
/// <summary>
/// Indicates whether the provided exception has an integer Number property with the supplied value
/// </summary>
public
static
bool
IsNumber
(
this
DbException
exception
,
int
number
)
=>
exception
!=
null
&&
ByTypeHelpers
.
Get
(
exception
.
GetType
()).
IsNumber
(
exception
,
number
);
private
sealed
class
ByTypeHelpers
{
private
static
readonly
ConcurrentDictionary
<
Type
,
ByTypeHelpers
>
s_byType
=
new
ConcurrentDictionary
<
Type
,
ByTypeHelpers
>();
private
readonly
Func
<
DbException
,
int
>?
_getNumber
;
public
bool
IsNumber
(
DbException
exception
,
int
number
)
=>
_getNumber
!=
null
&&
_getNumber
(
exception
)
==
number
;
public
static
ByTypeHelpers
Get
(
Type
type
)
{
if
(!
s_byType
.
TryGetValue
(
type
,
out
var
value
))
{
s_byType
[
type
]
=
value
=
new
ByTypeHelpers
(
type
);
}
return
value
;
}
private
ByTypeHelpers
(
Type
type
)
{
_getNumber
=
TryGetInstanceProperty
<
int
>(
"Number"
,
type
);
}
private
static
Func
<
DbException
,
T
>?
TryGetInstanceProperty
<
T
>(
string
name
,
Type
type
)
{
try
{
var
prop
=
type
.
GetProperty
(
name
,
BindingFlags
.
Public
|
BindingFlags
.
Instance
);
if
(
prop
==
null
||
!
prop
.
CanRead
)
return
null
;
if
(
prop
.
PropertyType
!=
typeof
(
T
))
return
null
;
var
p
=
Expression
.
Parameter
(
typeof
(
DbException
),
"exception"
);
var
body
=
Expression
.
Property
(
Expression
.
Convert
(
p
,
type
),
prop
);
var
lambda
=
Expression
.
Lambda
<
Func
<
DbException
,
T
>>(
body
,
p
);
return
lambda
.
Compile
();
}
catch
{
return
null
;
}
}
}
}
}
Dapper.ProviderTools/Internal/DynamicBulkCopy.cs
0 → 100644
View file @
3fe88fc1
using
System
;
using
System.Data
;
using
System.Data.Common
;
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Dapper.ProviderTools.Internal
{
internal
sealed
class
DynamicBulkCopy
:
BulkCopy
{
internal
static
BulkCopy
?
Create
(
object
?
wrapped
)
=>
wrapped
==
null
?
null
:
new
DynamicBulkCopy
(
wrapped
);
private
DynamicBulkCopy
(
object
wrapped
)
=>
_wrapped
=
wrapped
;
private
readonly
dynamic
_wrapped
;
public
override
string
DestinationTableName
{
get
=>
_wrapped
.
DestinationTableName
;
set
=>
_wrapped
.
DestinationTableName
=
value
;
}
public
override
object
Wrapped
=>
_wrapped
;
public
override
void
AddColumnMapping
(
string
sourceColumn
,
string
destinationColumn
)
=>
_wrapped
.
ColumnMappings
.
Add
(
sourceColumn
,
destinationColumn
);
public
override
void
AddColumnMapping
(
int
sourceColumn
,
int
destinationColumn
)
=>
_wrapped
.
ColumnMappings
.
Add
(
sourceColumn
,
destinationColumn
);
public
override
void
WriteToServer
(
DataTable
source
)
=>
_wrapped
.
WriteToServer
(
source
);
public
override
void
WriteToServer
(
IDataReader
source
)
=>
_wrapped
.
WriteToServer
(
source
);
public
override
Task
WriteToServerAsync
(
DbDataReader
source
,
CancellationToken
cancellationToken
)
=>
_wrapped
.
WriteToServer
(
source
,
cancellationToken
);
public
override
Task
WriteToServerAsync
(
DataTable
source
,
CancellationToken
cancellationToken
)
=>
_wrapped
.
WriteToServer
(
source
,
cancellationToken
);
protected
override
void
Dispose
(
bool
disposing
)
{
if
(
disposing
)
{
if
(
_wrapped
is
IDisposable
d
)
{
try
{
d
.
Dispose
();
}
catch
{
}
}
}
}
}
}
Dapper.Tests/Dapper.Tests.csproj
View file @
3fe88fc1
...
...
@@ -23,25 +23,23 @@
<ItemGroup>
<PackageReference Include="System.Data.SqlClient" Version="4.6.1" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="1.0.19239.1" />
<PackageReference Include="Microsoft.SqlServer.Types" Version="14.0.1016.290"
Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'" />
<PackageReference Include="Microsoft.SqlServer.Types" Version="14.0.1016.290" Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)'=='x64'">
<Content Include="$(USERPROFILE)\.nuget\packages\microsoft.sqlserver.types\14.0.1016.290\nativeBinaries\x64\*.dll"
Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'">
<Content Include="$(USERPROFILE)\.nuget\packages\microsoft.sqlserver.types\14.0.1016.290\nativeBinaries\x64\*.dll" Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="'$(Platform)'=='x86'">
<Content Include="$(USERPROFILE)\.nuget\packages\microsoft.sqlserver.types\14.0.1016.290\nativeBinaries\x86\*.dll"
Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'">
<Content Include="$(USERPROFILE)\.nuget\packages\microsoft.sqlserver.types\14.0.1016.290\nativeBinaries\x86\*.dll" Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Dapper.ProviderTools\Dapper.ProviderTools.csproj" />
<ProjectReference Include="..\Dapper\Dapper.csproj" />
<ProjectReference Include="..\Dapper.Contrib\Dapper.Contrib.csproj" />
<PackageReference Include="FirebirdSql.Data.FirebirdClient" Version="7.0.0" />
...
...
@@ -54,6 +52,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Oracle.ManagedDataAccess" Version="19.3.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'">
...
...
Dapper.Tests/ProviderTests.cs
0 → 100644
View file @
3fe88fc1
using
System.Data.Common
;
using
Dapper.ProviderTools
;
using
Xunit
;
namespace
Dapper.Tests
{
public
class
ProviderTests
{
[
Fact
]
public
void
BulkCopy_SystemDataSqlClient
()
{
using
(
var
conn
=
new
System
.
Data
.
SqlClient
.
SqlConnection
())
{
Test
<
System
.
Data
.
SqlClient
.
SqlBulkCopy
>(
conn
);
}
}
[
Fact
]
public
void
BulkCopy_MicrosoftDataSqlClient
()
{
using
(
var
conn
=
new
Microsoft
.
Data
.
SqlClient
.
SqlConnection
())
{
Test
<
Microsoft
.
Data
.
SqlClient
.
SqlBulkCopy
>(
conn
);
}
}
private
static
void
Test
<
T
>(
DbConnection
connection
)
{
using
(
var
bcp
=
BulkCopy
.
TryCreate
(
connection
))
{
Assert
.
NotNull
(
bcp
);
Assert
.
IsType
<
T
>(
bcp
.
Wrapped
);
bcp
.
EnableStreaming
=
true
;
}
}
[
Theory
]
[
InlineData
(
51000
,
51000
,
true
)]
[
InlineData
(
51000
,
43
,
false
)]
public
void
DbNumber_SystemData
(
int
create
,
int
test
,
bool
result
)
=>
Test
<
SystemSqlClientProvider
>(
create
,
test
,
result
);
[
Theory
]
[
InlineData
(
51000
,
51000
,
true
)]
[
InlineData
(
51000
,
43
,
false
)]
public
void
DbNumber_MicrosoftData
(
int
create
,
int
test
,
bool
result
)
=>
Test
<
MicrosoftSqlClientProvider
>(
create
,
test
,
result
);
private
void
Test
<
T
>(
int
create
,
int
test
,
bool
result
)
where
T
:
SqlServerDatabaseProvider
,
new
()
{
var
provider
=
new
T
();
using
(
var
conn
=
provider
.
GetOpenConnection
())
{
try
{
conn
.
Execute
(
"throw @create, 'boom', 1;"
,
new
{
create
});
Assert
.
False
(
true
);
}
catch
(
DbException
err
)
{
Assert
.
Equal
(
result
,
err
.
IsNumber
(
test
));
}
}
}
}
}
Dapper.sln
View file @
3fe88fc1
...
...
@@ -45,6 +45,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.EntityFramework.Stro
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests.Performance", "Dapper.Tests.Performance\Dapper.Tests.Performance.csproj", "{F017075A-2969-4A8E-8971-26F154EB420F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.ProviderTools", "Dapper.ProviderTools\Dapper.ProviderTools.csproj", "{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
...
...
@@ -91,6 +93,10 @@ Global
{F017075A-2969-4A8E-8971-26F154EB420F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F017075A-2969-4A8E-8971-26F154EB420F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F017075A-2969-4A8E-8971-26F154EB420F}.Release|Any CPU.Build.0 = Release|Any CPU
{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
...
...
@@ -106,6 +112,7 @@ Global
{8A74F0B6-188F-45D2-8A4B-51E4F211805A} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
{39D3EEB6-9C05-4F4A-8C01-7B209742A7EB} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
{F017075A-2969-4A8E-8971-26F154EB420F} = {568BD46C-1C65-4D44-870C-12CD72563262}
{B06DB435-0C74-4BD3-BC97-52AF7CF9916B} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {928A4226-96F3-409A-8A83-9E7444488710}
...
...
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