diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 42e4b28516..3c3336de1f 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -238,9 +238,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Dashboards", "src\Volo.Abp.AspNetCore.Mvc.UI.Dashboards\Volo.Abp.AspNetCore.Mvc.UI.Dashboards.csproj", "{054D766D-5992-460E-A4D8-936D80BE2C1A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ldap", "src\Volo.Abp.Ldap\Volo.Abp.Ldap.csproj", "{4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Ldap", "src\Volo.Abp.Ldap\Volo.Abp.Ldap.csproj", "{4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ldap.Tests", "test\Volo.Abp.Ldap.Tests\Volo.Abp.Ldap.Tests.csproj", "{38FB8F75-426E-4265-8D0E-E121837B6FCC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Ldap.Tests", "test\Volo.Abp.Ldap.Tests\Volo.Abp.Ldap.Tests.csproj", "{38FB8F75-426E-4265-8D0E-E121837B6FCC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Dapper", "src\Volo.Abp.Dapper\Volo.Abp.Dapper.csproj", "{D863A3C3-CC1D-426F-BDD4-02E7AE2A3170}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Dapper.Tests", "test\Volo.Abp.Dapper.Tests\Volo.Abp.Dapper.Tests.csproj", "{E026A085-D881-4AE0-9F08-422AC3903BD7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -720,6 +724,14 @@ Global
{38FB8F75-426E-4265-8D0E-E121837B6FCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38FB8F75-426E-4265-8D0E-E121837B6FCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38FB8F75-426E-4265-8D0E-E121837B6FCC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D863A3C3-CC1D-426F-BDD4-02E7AE2A3170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D863A3C3-CC1D-426F-BDD4-02E7AE2A3170}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D863A3C3-CC1D-426F-BDD4-02E7AE2A3170}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D863A3C3-CC1D-426F-BDD4-02E7AE2A3170}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E026A085-D881-4AE0-9F08-422AC3903BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E026A085-D881-4AE0-9F08-422AC3903BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E026A085-D881-4AE0-9F08-422AC3903BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E026A085-D881-4AE0-9F08-422AC3903BD7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -843,6 +855,8 @@ Global
{054D766D-5992-460E-A4D8-936D80BE2C1A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{4DADBBD2-4C63-4C90-9661-EBF6252A7D6F} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{38FB8F75-426E-4265-8D0E-E121837B6FCC} = {447C8A77-E5F0-4538-8687-7383196D04EA}
+ {D863A3C3-CC1D-426F-BDD4-02E7AE2A3170} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {E026A085-D881-4AE0-9F08-422AC3903BD7} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj b/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj
new file mode 100644
index 0000000000..849dc33c60
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj
@@ -0,0 +1,24 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.Dapper
+ Volo.Abp.Dapper
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Dapper/Volo/Abp/Dapper/AbpDapperModule.cs b/framework/src/Volo.Abp.Dapper/Volo/Abp/Dapper/AbpDapperModule.cs
new file mode 100644
index 0000000000..17045fd12b
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapper/Volo/Abp/Dapper/AbpDapperModule.cs
@@ -0,0 +1,13 @@
+using Volo.Abp.Domain;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.Dapper
+{
+ [DependsOn(
+ typeof(AbpDddDomainModule),
+ typeof(AbpEntityFrameworkCoreModule))]
+ public class AbpDapperModule : AbpModule
+ {
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs
new file mode 100644
index 0000000000..cdb03f8515
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs
@@ -0,0 +1,23 @@
+using System.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Storage;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Uow;
+
+namespace Volo.Abp.Domain.Repositories.Dapper
+{
+ public class DapperRepository : IDapperRepository, IUnitOfWorkEnabled
+ where TDbContext : IEfCoreDbContext
+ {
+ private readonly IDbContextProvider _dbContextProvider;
+
+ public DapperRepository(IDbContextProvider dbContextProvider)
+ {
+ _dbContextProvider = dbContextProvider;
+ }
+
+ public IDbConnection DbConnection => _dbContextProvider.GetDbContext().Database.GetDbConnection();
+
+ public IDbTransaction DbTransaction => _dbContextProvider.GetDbContext().Database.CurrentTransaction?.GetDbTransaction();
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs
new file mode 100644
index 0000000000..f45be08b54
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs
@@ -0,0 +1,11 @@
+using System.Data;
+
+namespace Volo.Abp.Domain.Repositories.Dapper
+{
+ public interface IDapperRepository
+ {
+ IDbConnection DbConnection { get; }
+
+ IDbTransaction DbTransaction { get; }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj b/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj
new file mode 100644
index 0000000000..c531932479
--- /dev/null
+++ b/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ netcoreapp2.2
+ Volo.Abp.Dapper.Tests
+ Volo.Abp.Dapper.Tests
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/AbpDapperTestModule.cs b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/AbpDapperTestModule.cs
new file mode 100644
index 0000000000..02b7575052
--- /dev/null
+++ b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/AbpDapperTestModule.cs
@@ -0,0 +1,17 @@
+using Volo.Abp.Autofac;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.Dapper
+{
+ [DependsOn(
+ typeof(AbpEntityFrameworkCoreTestModule),
+ typeof(AbpDapperModule),
+ typeof(AbpAutofacModule))]
+ public class AbpDapperTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/DapperTestBase.cs b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/DapperTestBase.cs
new file mode 100644
index 0000000000..3fa387cec2
--- /dev/null
+++ b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/DapperTestBase.cs
@@ -0,0 +1,10 @@
+namespace Volo.Abp.Dapper
+{
+ public abstract class DapperTestBase : AbpIntegratedTest
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs
new file mode 100644
index 0000000000..3621f9301e
--- /dev/null
+++ b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Dapper;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Repositories.Dapper;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.TestApp.EntityFrameworkCore;
+
+namespace Volo.Abp.Dapper.Repositories
+{
+ public class PersonDapperRepository : DapperRepository, ITransientDependency
+ {
+ public PersonDapperRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+
+ public virtual async Task> GetAllPersonNames()
+ {
+ return (await DbConnection.QueryAsync("select Name from People", transaction: DbTransaction))
+ .ToList();
+ }
+
+ public virtual async Task UpdatePersonNames(string name)
+ {
+ return await DbConnection.ExecuteAsync("update People set Name = @NewName", new {NewName = name},
+ DbTransaction);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository_Tests.cs b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository_Tests.cs
new file mode 100644
index 0000000000..3b5a7a4dd3
--- /dev/null
+++ b/framework/test/Volo.Abp.Dapper.Tests/Volo/Abp/Dapper/Repositories/PersonDapperRepository_Tests.cs
@@ -0,0 +1,52 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.TestApp;
+using Volo.Abp.Uow;
+using Xunit;
+
+namespace Volo.Abp.Dapper.Repositories
+{
+ public class PersonDapperRepository_Tests : DapperTestBase
+ {
+ [Fact]
+ public async Task GetAllPersonNames_Test()
+ {
+ var allNames = await GetRequiredService().GetAllPersonNames();
+ allNames.ShouldNotBeEmpty();
+ allNames.ShouldContain(x => x == "Douglas");
+ allNames.ShouldContain(x => x == "John-Deleted");
+ allNames.ShouldContain(x => x == $"{TestDataBuilder.TenantId1}-Person1");
+ allNames.ShouldContain(x => x == $"{TestDataBuilder.TenantId1}-Person2");
+ }
+
+ [Fact]
+ public async Task UpdatePersonNames_Test()
+ {
+ var personDapperRepository = GetRequiredService();
+ await personDapperRepository.UpdatePersonNames("test");
+
+ var allNames = await personDapperRepository.GetAllPersonNames();
+ allNames.ShouldNotBeEmpty();
+ allNames.ShouldAllBe(x => x == "test");
+ }
+
+ [Fact]
+ public async Task Dapper_Transaction_Test()
+ {
+ var unitOfWorkManager = GetRequiredService();
+ var personDapperRepository = GetRequiredService();
+
+ using (var uow = unitOfWorkManager.Begin(new UnitOfWorkOptions
+ {
+ IsTransactional = true
+ }))
+ {
+ await personDapperRepository.UpdatePersonNames("test");
+ await uow.RollbackAsync();
+ }
+
+ var allNames = await personDapperRepository.GetAllPersonNames();
+ allNames.ShouldAllBe(x => x != "test");
+ }
+ }
+}
\ No newline at end of file