大家好,首先原谅我标题是英文的,因为我想不出好的中文标题。

这里我个人写了一个Dapper.net 的Repository模式的底层基础框架。

涉及内容:

Dapper.net结合Repository的设计,可切换不同数据库及当前操作数据库的事务支持,依赖注入(工具:Autofac)。

项目可直接在此基础框架上开发。

该底层架构分层参考:

Nopcommerce:https://www.nopcommerce.com

以及自己累积的经验分层及设计

项目结构图:

DapperRepository.Core: 放置相关数据接口和实体类

DapperRepository.Data:数据操作层,实现具体Repository和数据库连接及访问

DapperRepository.Services:业务逻辑层,处理相关业务逻辑

DapperRepository.Web:web端,客户端操作

以下简称Core、Data、Services、Web

数据库脚本:

创建数据库:

USE [master]
GO /****** Object: Database [DapperRepositoryDb] Script Date: 2/28/2019 2:59:41 PM ******/
CREATE DATABASE [DapperRepositoryDb]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'DapperRepositoryDb', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\DapperRepositoryDb.mdf' , SIZE = 4096KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'DapperRepositoryDb_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\DapperRepositoryDb_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO ALTER DATABASE [DapperRepositoryDb] SET COMPATIBILITY_LEVEL = 110
GO IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [DapperRepositoryDb].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO ALTER DATABASE [DapperRepositoryDb] SET ANSI_NULL_DEFAULT OFF
GO ALTER DATABASE [DapperRepositoryDb] SET ANSI_NULLS OFF
GO ALTER DATABASE [DapperRepositoryDb] SET ANSI_PADDING OFF
GO ALTER DATABASE [DapperRepositoryDb] SET ANSI_WARNINGS OFF
GO ALTER DATABASE [DapperRepositoryDb] SET ARITHABORT OFF
GO ALTER DATABASE [DapperRepositoryDb] SET AUTO_CLOSE OFF
GO ALTER DATABASE [DapperRepositoryDb] SET AUTO_CREATE_STATISTICS ON
GO ALTER DATABASE [DapperRepositoryDb] SET AUTO_SHRINK OFF
GO ALTER DATABASE [DapperRepositoryDb] SET AUTO_UPDATE_STATISTICS ON
GO ALTER DATABASE [DapperRepositoryDb] SET CURSOR_CLOSE_ON_COMMIT OFF
GO ALTER DATABASE [DapperRepositoryDb] SET CURSOR_DEFAULT GLOBAL
GO ALTER DATABASE [DapperRepositoryDb] SET CONCAT_NULL_YIELDS_NULL OFF
GO ALTER DATABASE [DapperRepositoryDb] SET NUMERIC_ROUNDABORT OFF
GO ALTER DATABASE [DapperRepositoryDb] SET QUOTED_IDENTIFIER OFF
GO ALTER DATABASE [DapperRepositoryDb] SET RECURSIVE_TRIGGERS OFF
GO ALTER DATABASE [DapperRepositoryDb] SET DISABLE_BROKER
GO ALTER DATABASE [DapperRepositoryDb] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO ALTER DATABASE [DapperRepositoryDb] SET DATE_CORRELATION_OPTIMIZATION OFF
GO ALTER DATABASE [DapperRepositoryDb] SET TRUSTWORTHY OFF
GO ALTER DATABASE [DapperRepositoryDb] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO ALTER DATABASE [DapperRepositoryDb] SET PARAMETERIZATION SIMPLE
GO ALTER DATABASE [DapperRepositoryDb] SET READ_COMMITTED_SNAPSHOT OFF
GO ALTER DATABASE [DapperRepositoryDb] SET HONOR_BROKER_PRIORITY OFF
GO ALTER DATABASE [DapperRepositoryDb] SET RECOVERY SIMPLE
GO ALTER DATABASE [DapperRepositoryDb] SET MULTI_USER
GO ALTER DATABASE [DapperRepositoryDb] SET PAGE_VERIFY CHECKSUM
GO ALTER DATABASE [DapperRepositoryDb] SET DB_CHAINING OFF
GO ALTER DATABASE [DapperRepositoryDb] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO ALTER DATABASE [DapperRepositoryDb] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO ALTER DATABASE [DapperRepositoryDb] SET READ_WRITE
GO

创建表和演示数据:

USE [DapperRepositoryDb]
GO /****** Object: Table [dbo].[Customer] Script Date: 2019/2/28 14:54:06 ******/
SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO CREATE TABLE [dbo].[Customer](
[Id] [INT] IDENTITY(1,1) NOT NULL,
[Username] [NVARCHAR](32) NOT NULL,
[Email] [NVARCHAR](128) NOT NULL,
[Active] [BIT] NOT NULL,
[CreationTime] [DATETIME] NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO /****** Object: Table [dbo].[CustomerRole] Script Date: 2019/2/28 14:54:26 ******/
SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO CREATE TABLE [dbo].[CustomerRole](
[Id] [INT] IDENTITY(1,1) NOT NULL,
[Name] [NVARCHAR](32) NOT NULL,
[SystemName] [NVARCHAR](32) NOT NULL,
[CreationTime] [DATETIME] NOT NULL,
CONSTRAINT [PK_CustomerRole] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO /****** Object: Table [dbo].[Customer_CustomerRole_Mapping] Script Date: 2019/2/28 14:54:40 ******/
SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO CREATE TABLE [dbo].[Customer_CustomerRole_Mapping](
[CustomerId] [INT] NOT NULL,
[CustomerRoleId] [INT] NOT NULL
) ON [PRIMARY] GO ALTER TABLE [dbo].[Customer_CustomerRole_Mapping] WITH CHECK ADD CONSTRAINT [FK_Customer_CustomerRole_Mapping_Customer] FOREIGN KEY([CustomerId])
REFERENCES [dbo].[Customer] ([Id])
ON DELETE CASCADE
GO ALTER TABLE [dbo].[Customer_CustomerRole_Mapping] CHECK CONSTRAINT [FK_Customer_CustomerRole_Mapping_Customer]
GO ALTER TABLE [dbo].[Customer_CustomerRole_Mapping] WITH CHECK ADD CONSTRAINT [FK_Customer_CustomerRole_Mapping_CustomerRole] FOREIGN KEY([CustomerRoleId])
REFERENCES [dbo].[CustomerRole] ([Id])
ON DELETE CASCADE
GO ALTER TABLE [dbo].[Customer_CustomerRole_Mapping] CHECK CONSTRAINT [FK_Customer_CustomerRole_Mapping_CustomerRole]
GO INSERT INTO [dbo].[CustomerRole]
([Name]
,[SystemName]
,[CreationTime])
VALUES
('Admin',
'Admin',
GETDATE())
GO INSERT INTO [dbo].[CustomerRole]
([Name]
,[SystemName]
,[CreationTime])
VALUES
('Guest',
'Guest',
GETDATE())
GO

接下俩详细分析:

实体基类BaseEntity:

namespace DapperRepository.Core
{
public abstract class BaseEntity
{
public int Id { get; set; }
}
}

Core:

建立一个名为Data的文件夹放置IDbSession和IRepository:

IDbSession:

using System;
using System.Data; namespace DapperRepository.Core.Data
{
public interface IDbSession : IDisposable
{
IDbConnection Connection { get; }
IDbTransaction Transaction { get; } IDbTransaction BeginTrans(IsolationLevel isolation = IsolationLevel.ReadCommitted);
void Commit();
void Rollback();
}
}

这个接口定义数据数据连接对象属性和事务属性,以及相关事务性的操作方法。

IRepository:

using System.Data;
using System.Collections.Generic; namespace DapperRepository.Core.Data
{
public interface IRepository<T> where T : BaseEntity
{
/// <summary>
/// 根据主键获取一条数据
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="buffered">是否缓冲查询数据,详细信息:https://dapper-tutorial.net/buffered </param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>当前查询数据</returns>
T GetById(string sql, object param = null, bool buffered = true, int? commandTimeout = null,
CommandType? commandType = null, bool useTransaction = false); /// <summary>
/// 根据相关条件获取一条数据
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="buffered">是否缓冲查询数据,详细信息:https://dapper-tutorial.net/buffered </param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>当前查询数据</returns>
T GetBy(string sql, object param = null, bool buffered = true, int? commandTimeout = null,
CommandType? commandType = null, bool useTransaction = false); /// <summary>
/// 获取数据列表(所有、部分或者分页获取)
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="buffered">是否缓冲查询数据,详细信息:https://dapper-tutorial.net/buffered </param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>当前查询数据列表</returns>
IEnumerable<T> GetList(string sql, object param = null, bool buffered = true, int? commandTimeout = null,
CommandType? commandType = null, bool useTransaction = false); /// <summary>
/// 添加数据
/// </summary>
/// <param name="entity">要添加的实体对象</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行结果(一般为添加的Id)</returns>
dynamic Insert(T entity, int? commandTimeout = null, bool useTransaction = false); /// <summary>
/// 修改数据
/// </summary>
/// <param name="entity">要修改的实体对象</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行结果(true or false)</returns>
bool Update(T entity, int? commandTimeout = null, bool useTransaction = false); /// <summary>
/// 删除数据
/// </summary>
/// <param name="entity">要删除的实体对象</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行结果(true or false)</returns>
bool Delete(T entity, int? commandTimeout = null, bool useTransaction = false); /// <summary>
/// 执行对象sql语句(一般需要事务处理)
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行受影响的行数</returns>
int Execute(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null,
bool useTransaction = true);
}
}

这里定义相关数据操作(增删查改)的基础方法。或许有些开发者会问为何分页,执行存储过程的基础方法都没有。这里我个人说明下,因为dapper.net是精简orm,并不像EF那样集成了很多方法和扩展,dapper主要还是依赖于写的sql语句的处理逻辑。所以这里分页的话你写好sql语句或者存储过程并调用GetList方法即可。

创建一个名为Domain的文件夹放置相关实体:

DataBaseType枚举(数据库类型:MSSQL、MYSQL、ORACLE...)

namespace DapperRepository.Core.Domain
{
public enum DatabaseType
{
Mssql,
Mysql,
Oracle
}
}

相关实体:

Customer:

using System;

namespace DapperRepository.Core.Domain.Customers
{
public class Customer : BaseEntity
{
public string Username { get; set; } public string Email { get; set; } public bool Active { get; set; } public DateTime CreationTime { get; set; }
}
}

CustomerRole:

namespace DapperRepository.Core.Domain.Customers
{
public class CustomerRole : BaseEntity
{
public string Name { get; set; } public string SystemName { get; set; }
}
}

Dto实体CustomerDtoModel:

using System;

namespace DapperRepository.Core.Domain.Customers
{
public class CustomerDtoModel
{
public int Id { get; set; } public string Username { get; set; } public string Email { get; set; } public bool Active { get; set; } public DateTime CreationTime { get; set; } public virtual CustomerRole CustomerRole { get; set; }
}
}

Data:

新建一个类ConnConfig用于获取数据连接字符串:

using System.Configuration;
using System.Web.Configuration; namespace DapperRepository.Data
{
public class ConnConfig
{
private readonly static Configuration Config = WebConfigurationManager.OpenWebConfiguration("~"); /// <summary>
/// mssql 连接字符串
/// </summary>
private static string _mssqlConnectionString = Config.AppSettings.Settings["MssqlConnectionString"].Value;
/// <summary>
/// mysql 连接字符串
/// </summary>
private static string _mysqlConnectionString = Config.AppSettings.Settings["MysqlConnectionString"].Value;
/// <summary>
/// oracle 连接字符串
/// </summary>
private static string _oracleConnectionString = Config.AppSettings.Settings["OracleConnectionString"].Value; public static string MssqlConnectionString
{
get { return _mssqlConnectionString; }
set { _mssqlConnectionString = value; }
} public static string MysqlConnectionString
{
get { return _mysqlConnectionString; }
set { _mysqlConnectionString = value; }
} public static string OracleConnectionString
{
get { return _oracleConnectionString; }
set { _oracleConnectionString = value; }
}
}
}

工厂类SessionFactory用于切换某个数据库以及创建数据库会话:

using System.Data;
using System.Data.OracleClient;
using System.Data.SqlClient;
using DapperRepository.Core.Data;
using DapperRepository.Core.Domain;
using MySql.Data.MySqlClient; namespace DapperRepository.Data
{
public class SessionFactory
{
private static IDbConnection CreateConnection(DatabaseType dataType)
{
IDbConnection conn;
switch (dataType)
{
case DatabaseType.Mssql:
conn = new SqlConnection(ConnConfig.MssqlConnectionString);
break;
case DatabaseType.Mysql:
conn = new MySqlConnection(ConnConfig.MysqlConnectionString);
break;
case DatabaseType.Oracle:
conn = new OracleConnection(ConnConfig.OracleConnectionString);
break;
default:
conn = new SqlConnection(ConnConfig.MssqlConnectionString);
break;
} conn.Open(); return conn;
} /// <summary>
/// 创建数据库连接会话
/// </summary>
/// <returns></returns>
public static IDbSession CreateSession(DatabaseType databaseType)
{
IDbConnection conn = CreateConnection(databaseType);
IDbSession session = new DbSession(conn);
return session;
}
}
}

IDbSession的实现类DbSession:

using System;
using System.Data;
using DapperRepository.Core.Data; namespace DapperRepository.Data
{
public class DbSession : IDbSession
{
private IDbConnection _connection;
private IDbTransaction _transaction; public DbSession(IDbConnection conn)
{
_connection = conn;
} public IDbConnection Connection
{
get { return _connection; }
} public IDbTransaction Transaction
{
get { return _transaction; }
} public IDbTransaction BeginTrans(IsolationLevel isolation = IsolationLevel.ReadCommitted)
{
_transaction = _connection.BeginTransaction(isolation); return _transaction;
} public void Commit()
{
_transaction.Commit();
} public void Rollback()
{
_transaction.Rollback();
} public void Dispose()
{
if (_transaction != null)
{
_transaction.Dispose();
_transaction = null;
} if (_connection != null)
{
if (_connection.State == ConnectionState.Open)
_connection.Close(); _connection.Dispose();
_connection = null;
} GC.SuppressFinalize(this);
}
}
}

抽象类RepositoryBase用于实现IRepository接口的方法:

using System;
using System.Linq;
using System.Data;
using System.Collections.Generic;
using Dapper;
using DapperExtensions;
using DapperRepository.Core;
using DapperRepository.Core.Data;
using DapperRepository.Core.Domain; namespace DapperRepository.Data
{
public abstract class RepositoryBase<T> where T : BaseEntity
{
protected virtual IDbSession DbSession
{
get { return SessionFactory.CreateSession(DataType); }
} /// <summary>
/// 数据库类型(MSSQL,MYSQL...)
/// </summary>
protected abstract DatabaseType DataType { get; } /// <summary>
/// 根据主键获取一条数据
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="buffered">是否缓冲查询数据,详细信息:https://dapper-tutorial.net/buffered </param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>当前查询数据</returns>
public virtual T GetById(string sql, object param = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null, bool useTransaction = false)
{
if (string.IsNullOrEmpty(sql))
return null; IDbSession session = DbSession; T result = session.Connection.Query<T>(sql, param, null, buffered, commandTimeout, commandType).SingleOrDefault(); session.Dispose(); // 释放资源 return result;
} /// <summary>
/// 根据相关条件获取一条数据
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="buffered">是否缓冲查询数据,详细信息:https://dapper-tutorial.net/buffered </param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>当前查询数据</returns>
public virtual T GetBy(string sql, object param = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null, bool useTransaction = false)
{
if (string.IsNullOrEmpty(sql))
return null; IDbSession session = DbSession; T result = session.Connection.Query<T>(sql, param, null, buffered, commandTimeout, commandType).FirstOrDefault(); session.Dispose(); // 释放资源 return result;
} /// <summary>
/// 获取数据列表(所有、部分或者分页获取)
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="buffered">是否缓冲查询数据,详细信息:https://dapper-tutorial.net/buffered </param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>当前查询数据列表</returns>
public virtual IEnumerable<T> GetList(string sql, object param = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null, bool useTransaction = false)
{
if (string.IsNullOrEmpty(sql))
return null; IEnumerable<T> results; IDbSession session = DbSession;
if (useTransaction)
{
session.BeginTrans(); results = session.Connection.Query<T>(sql, param, session.Transaction, buffered, commandTimeout, commandType).ToList();
session.Commit();
}
else
{
results = session.Connection.Query<T>(sql, param, null, buffered, commandTimeout, commandType).ToList();
} session.Dispose(); // 释放资源 return results;
} /// <summary>
/// 添加数据
/// </summary>
/// <param name="entity">要添加的实体对象</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行结果(一般为添加的Id)</returns>
public virtual dynamic Insert(T entity, int? commandTimeout = null, bool useTransaction = false)
{
IDbSession session = DbSession; try
{
if (useTransaction)
{
session.BeginTrans(); dynamic result = session.Connection.Insert(entity, session.Transaction, commandTimeout);
session.Commit();
return result;
}
else
{
return session.Connection.Insert(entity, null, commandTimeout);
}
}
catch (Exception)
{
if (useTransaction)
{
session.Rollback();
} return null;
}
finally
{
session.Dispose(); // 释放资源
}
} /// <summary>
/// 修改数据
/// </summary>
/// <param name="entity">要修改的实体对象</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行结果(true or false)</returns>
public virtual bool Update(T entity, int? commandTimeout = null, bool useTransaction = false)
{
IDbSession session = DbSession; try
{
if (useTransaction)
{
session.BeginTrans(); bool result = session.Connection.Update(entity, session.Transaction, commandTimeout);
session.Commit();
return result;
}
else
{
return session.Connection.Update(entity, null, commandTimeout);
}
}
catch (Exception)
{
if (useTransaction)
{
session.Rollback();
} return false;
}
finally
{
session.Dispose(); // 释放资源
}
} /// <summary>
/// 删除数据
/// </summary>
/// <param name="entity">要删除的实体对象</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行结果(true or false)</returns>
public virtual bool Delete(T entity, int? commandTimeout = null, bool useTransaction = false)
{
IDbSession session = DbSession; try
{
if (useTransaction)
{
session.BeginTrans(); bool result = session.Connection.Delete(entity, session.Transaction, commandTimeout);
session.Commit();
return result;
}
else
{
return session.Connection.Delete(entity, null, commandTimeout);
}
}
catch (Exception)
{
if (useTransaction)
{
session.Rollback();
} return false;
}
finally
{
session.Dispose(); // 释放资源
}
} /// <summary>
/// 执行对象sql语句(一般需要事务处理)
/// </summary>
/// <param name="sql">sql语句或者存储过程</param>
/// <param name="param">语句参数</param>
/// <param name="commandTimeout">执行超时时间</param>
/// <param name="commandType">命令类型(sql语句或是存储过程)</param>
/// <param name="useTransaction">是否开启事务</param>
/// <returns>执行受影响的行数</returns>
public virtual int Execute(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null, bool useTransaction = true)
{
if (string.IsNullOrEmpty(sql))
return 0; IDbSession session = DbSession; try
{
if (useTransaction)
{
session.BeginTrans(); int rowsAffected = session.Connection.Execute(sql, param, session.Transaction, commandTimeout, commandType);
session.Commit(); return rowsAffected;
}
else
{
return session.Connection.Execute(sql, param, null, commandTimeout, commandType);
}
}
catch (Exception)
{
if (useTransaction)
{
session.Rollback();
} return 0;
}
finally
{
session.Dispose(); // 释放资源
}
}
}
}

新建接口ICustomerRepository:

using System.Collections.Generic;
using DapperRepository.Core.Data;
using DapperRepository.Core.Domain.Customers; namespace DapperRepository.Data.Repositories.Customers
{
public interface ICustomerRepository : IRepository<Customer>
{
#region Customer Customer GetCustomerById(int id); CustomerDtoModel GetCustomerBy(int id); IEnumerable<CustomerDtoModel> GetAllCustomers(); int InsertCustomer(Customer customer, int roleId);
int UpdateCustomer(Customer customer, int roleId); #endregion #region Customer Roles // IEnumerable<CustomerRole> GetCustomerRoles(); #endregion
}
}

对应实现类CustomerRepository:

using System;
using System.Text;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using Dapper;
using DapperRepository.Core.Data;
using DapperRepository.Core.Domain;
using DapperRepository.Core.Domain.Customers; namespace DapperRepository.Data.Repositories.Customers
{
public class CustomerRepository : RepositoryBase<Customer>, ICustomerRepository
{
protected override DatabaseType DataType
{
get { return DatabaseType.Mssql; }
} public Customer GetCustomerById(int id)
{
if (id == 0)
return null; const string sql = "SELECT [Id],[Username],[Email],[Active],[CreationTime] FROM Customer WHERE Id=@id";
return GetById(sql, new { id }, commandType: CommandType.Text);
} public CustomerDtoModel GetCustomerBy(int id)
{
StringBuilder sb = new StringBuilder();
sb.Append("SELECT c.Id,c.Username,c.Email,c.Active,c.CreationTime,cr.Id,cr.Name,cr.SystemName FROM Customer c ");
sb.Append("JOIN Customer_CustomerRole_Mapping crm ON c.Id = crm.CustomerId ");
sb.Append("JOIN CustomerRole cr ON crm.CustomerRoleId = cr.Id WHERE c.Id = @id"); string sql = sb.ToString();
IDbSession session = DbSession; using (IDbConnection conn = session.Connection)
{
var customers = conn.Query<CustomerDtoModel, CustomerRole, CustomerDtoModel>(sql, (c, cr) =>
{
c.CustomerRole = cr;
return c;
}, new { id }).FirstOrDefault(); return customers;
}
} public IEnumerable<CustomerDtoModel> GetAllCustomers()
{
StringBuilder sb = new StringBuilder();
sb.Append("SELECT c.Id,c.Username,c.Email,c.Active,c.CreationTime,cr.Id,cr.Name,cr.SystemName FROM Customer c ");
sb.Append("JOIN Customer_CustomerRole_Mapping crm ON c.Id = crm.CustomerId ");
sb.Append("JOIN CustomerRole cr ON crm.CustomerRoleId = cr.Id"); string sql = sb.ToString();
IDbSession session = DbSession;
try
{
using (IDbConnection conn = session.Connection)
{
session.BeginTrans(); var customers = conn.Query<CustomerDtoModel, CustomerRole, CustomerDtoModel>(sql, (c, cr) =>
{
c.CustomerRole = cr;
return c;
}, transaction: session.Transaction);
session.Commit(); return customers;
}
}
catch (Exception)
{
return null;
}
finally
{
session.Dispose();
}
} public int InsertCustomer(Customer customer, int roleId)
{
StringBuilder builder = new StringBuilder(50);
builder.Append("DECLARE @insertid INT;");
builder.Append("INSERT INTO dbo.Customer( Username,Email,Active,CreationTime ) VALUES ( @Username,@Email,@Active,@CreationTime );");
builder.Append("SET @insertid = SCOPE_IDENTITY();");
builder.Append("INSERT INTO [dbo].[Customer_CustomerRole_Mapping]( CustomerId,CustomerRoleId ) VALUES ( @insertid,@roleId );"); return Execute(builder.ToString(), new
{
customer.Username,
customer.Email,
customer.Active,
customer.CreationTime,
roleId
}, commandType: CommandType.Text);
} /// <summary>
/// 更新信息(事实上用户有可能具有多个角色,我这里为了演示方便就假设用户只有一个角色处理了)
/// </summary>
/// <param name="customer"></param>
/// <param name="roleId">对应角色id</param>
/// <returns></returns>
public int UpdateCustomer(Customer customer, int roleId)
{
StringBuilder builder = new StringBuilder(50);
builder.Append("UPDATE [dbo].[Customer] SET [Username] = @Username,[Email] = @Email,[Active] = @Active WHERE [Id] = @Id;");
builder.Append("UPDATE [dbo].[Customer_CustomerRole_Mapping] SET [CustomerRoleId] = @CustomerRoleId WHERE [CustomerId] = @CustomerId;"); return Execute(builder.ToString(), new
{
customer.Username,
customer.Email,
customer.Active,
customer.Id,
@CustomerRoleId = roleId,
@CustomerId = customer.Id
}, commandType: CommandType.Text);
} #region Customer Roles
/*
public IEnumerable<CustomerRole> GetCustomerRoles()
{
const string sql = "SELECT Id,Name,SystemName FROM CustomerRole"; IDbSession session = DbSession; try
{
using (IDbConnection conn = session.Connection)
{
session.BeginTrans(); IEnumerable<CustomerRole> result = conn.Query<CustomerRole>(sql, transaction: session.Transaction);
session.Commit(); return result;
}
}
catch (Exception)
{
return null;
}
finally
{
session.Dispose();
}
}
*/
#endregion
}
}

Services:

接口ICustomerService:

using System.Collections.Generic;
using DapperRepository.Core.Domain.Customers; namespace DapperRepository.Services.Customers
{
public interface ICustomerService
{
#region Customer Customer GetCustomerById(int customerId); CustomerDtoModel GetCustomerBy(int id); IEnumerable<CustomerDtoModel> GetAllCustomers(); int InsertCustomer(Customer customer, int roleId); int UpdateCustomer(Customer customer, int roleId); bool DeleteCustomer(Customer customer); #endregion #region CustomerRole //IEnumerable<CustomerRole> GetCustomerRoles(); #endregion
}
}

对应实现类CustomerService:

using System;
using System.Collections.Generic;
using DapperRepository.Core.Domain.Customers;
using DapperRepository.Data.Repositories.Customers; namespace DapperRepository.Services.Customers
{
public class CustomerService : ICustomerService
{
private readonly ICustomerRepository _repository; public CustomerService(ICustomerRepository repository)
{
_repository = repository;
} #region Custoemr public Customer GetCustomerById(int customerId)
{
if (customerId == 0)
return null; return _repository.GetCustomerById(customerId);
} public CustomerDtoModel GetCustomerBy(int id)
{
if (id <= 0)
return null; return _repository.GetCustomerBy(id);
} public IEnumerable<CustomerDtoModel> GetAllCustomers()
{
return _repository.GetAllCustomers();
} public int InsertCustomer(Customer customer, int roleId)
{
if (customer == null)
throw new ArgumentNullException("customer"); return _repository.InsertCustomer(customer, roleId);
} public int UpdateCustomer(Customer customer, int roleId)
{
if (customer == null)
throw new ArgumentNullException("customer"); return _repository.UpdateCustomer(customer, roleId);
} public bool DeleteCustomer(Customer customer)
{
return _repository.Delete(customer);
} #endregion #region Customer Roles
/*
public IEnumerable<CustomerRole> GetCustomerRoles()
{
return _repository.GetCustomerRoles();
}
*/
#endregion
}
}

Web:

建立文件夹Infrastructure用于存放依赖注入的配置类Bootstrapper:

using System.Reflection;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
using DapperRepository.Data.Repositories.Customers;
using DapperRepository.Services.Customers; namespace DapperRepository.Web.Infrastructure
{
public class Bootstrapper
{
public static void Run()
{
SetAutofacContainer();
} private static void SetAutofacContainer()
{
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterControllers(Assembly.GetExecutingAssembly()); // Repositories
builder.RegisterType<CustomerRepository>().As<ICustomerRepository>().InstancePerLifetimeScope();
builder.RegisterType<CustomerRoleRepository>().As<ICustomerRoleRepository>().InstancePerLifetimeScope(); // Services
builder.RegisterType<CustomerService>().As<ICustomerService>().InstancePerLifetimeScope();
builder.RegisterType<CustomerRoleService>().As<ICustomerRoleService>().InstancePerLifetimeScope(); IContainer container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
}

添加控制器CustomerController:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using DapperRepository.Core.Domain.Customers;
using DapperRepository.Services.Customers;
using DapperRepository.Web.Models.Customers; namespace DapperRepository.Web.Controllers
{
public class CustomerController : Controller
{
private readonly ICustomerService _customerService;
private readonly ICustomerRoleService _customerRoleService; public CustomerController(ICustomerService customerService, ICustomerRoleService customerRoleService)
{
_customerService = customerService;
_customerRoleService = customerRoleService;
} public ActionResult Index()
{
IEnumerable<CustomerDtoModel> customers = _customerService.GetAllCustomers();
return View(customers);
} public ActionResult Create()
{
var customerRoles = _customerRoleService.GetCustomerRoles().Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
}).ToList(); CustomerModel model = new CustomerModel
{
AvailableRoles = customerRoles
}; return View(model);
} [HttpPost]
public ActionResult Create(CustomerModel model)
{
if (ModelState.IsValid)
{
Customer customer = new Customer
{
Username = model.Username,
Email = model.Email,
Active = model.Active,
CreationTime = DateTime.Now
}; _customerService.InsertCustomer(customer, model.RoleId);
}
return RedirectToAction("Index");
} public ActionResult Edit(int id)
{
CustomerDtoModel customer = _customerService.GetCustomerBy(id);
if (customer == null)
return RedirectToAction("Index"); var customerRoles = _customerRoleService.GetCustomerRoles().Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString(),
Selected = x.Id == customer.CustomerRole.Id
}).ToList(); CustomerModel model = new CustomerModel
{
Id = customer.Id,
Username = customer.Username,
Email = customer.Email,
Active = customer.Active,
CreationTime = customer.CreationTime,
RoleId = customer.CustomerRole.Id,
AvailableRoles = customerRoles
}; return View(model);
} [HttpPost]
public ActionResult Edit(CustomerModel model)
{
Customer customer = _customerService.GetCustomerById(model.Id);
if (customer == null)
return RedirectToAction("Index"); if (ModelState.IsValid)
{
customer.Username = model.Username;
customer.Email = model.Email;
customer.Active = model.Active; _customerService.UpdateCustomer(customer, model.RoleId);
}
return RedirectToAction("Index");
} [HttpPost]
public ActionResult Delete(int id)
{
Customer customer = _customerService.GetCustomerById(id);
if (customer == null)
return Json(new { status = false, msg = "No customer found with the specified id" }); try
{
bool result = _customerService.DeleteCustomer(customer);
return Json(new { status = result, msg = result ? "deleted successfully" : "deleted failed" });
}
catch (Exception ex)
{
return Json(new { status = false, msg = ex.Message });
}
}
}
}

Index.cshtml:

@model IEnumerable<DapperRepository.Core.Domain.Customers.CustomerDtoModel>
@{
ViewBag.Title = "Index";
} <h2>Data List</h2>
<div class="content-header clearfix">
<h5 class="pull-left">
<a href="@Url.Action("Create")" class="btn btn-primary">Add</a>
</h5>
</div>
<table class="table table-bordered">
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Role</th>
<th>Active</th>
<th>CreationTime</th>
<th>Action</th>
@foreach (var item in Model)
{
<tr>
<td>@item.Id</td>
<td>@item.Username</td>
<td>@item.Email</td>
<td>@item.CustomerRole.Name</td>
<td>@item.Active</td>
<td>@item.CreationTime</td>
<td>
<a class="btn btn-default" href="@Url.Action("Edit", new {id = item.Id})">Edit</a>
<a class="btn btn-default del" href="javascript:void(0)" data-id="@item.Id">Delete</a>
</td>
</tr>
}
</table>
<script>
$(function () {
$('a.del').click(function () {
if (confirm("Are you sure to delete the data?")) {
$.ajax({
url: "@Url.Action("Delete")",
type: "POST",
data: { id: $(this).data("id") }
}).done(function (data) {
if (data.status) {
location.reload();
} else {
console.log(data.msg);
}
}).error(function (xhr) {
console.log(xhr.message);
});
}
});
})
</script>

相关Create.cshtml及Edit.cshtml这里我就不给出了,大家可下载完整项目。

GitHub地址:https://github.com/Olek-HZQ/DapperRepositoryDemo

项目演示地址:http://dapperrepository.coolwecool.com

Dapper and Repository Pattern in MVC的更多相关文章

  1. Using the Repository Pattern with ASP.NET MVC and Entity Framework

    原文:http://www.codeguru.com/csharp/.net/net_asp/mvc/using-the-repository-pattern-with-asp.net-mvc-and ...

  2. 学习笔记之ASP.NET MVC & MVVM & The Repository Pattern

    ASP.NET MVC | The ASP.NET Site https://www.asp.net/mvc ASP.NET MVC gives you a powerful, patterns-ba ...

  3. [转]Using the Repository Pattern with ASP.NET MVC and Entity Framework

    本文转自:http://www.codeguru.com/csharp/.net/net_asp/mvc/using-the-repository-pattern-with-asp.net-mvc-a ...

  4. Follow me to learn what is repository pattern

    Introduction Creating a generic repository pattern in an mvc application with entity framework is th ...

  5. Laravel与Repository Pattern(仓库模式)

    为什么要学习Repository Pattern(仓库模式) Repository 模式主要思想是建立一个数据操作代理层,把controller里的数据操作剥离出来,这样做有几个好处: 把数据处理逻辑 ...

  6. Generic repository pattern and Unit of work with Entity framework

    原文 Generic repository pattern and Unit of work with Entity framework Repository pattern is an abstra ...

  7. Dapper结合Repository模式的应用

    Dapper结合Repository模式的应用,包括如何在数据访问层(DAL)使用Dapper组件. Dapper在真实项目中使用,扩展IDbConnection的功能,支持Oracle.MS SQL ...

  8. Using Repository Pattern in Entity Framework

    One of the most common pattern is followed in the world of Entity Framework is “Repository Pattern”. ...

  9. How To Use The Repository Pattern In Laravel

    The Repository Pattern in Laravel is a very useful pattern with a couple of great uses. The first us ...

随机推荐

  1. #if #endif #elif #undef

    #define aaa           //放在代码最前面 int a = 1; a = a + 1; #if !aaa {a = a + 1;}#elif !aaaaa {a=a+11;}#en ...

  2. ps_cc:制作sprite拼贴图片

    我们的目标是: 将   合并为一张图片   step1:制作动作,便于批处理和重复使用 首先随便新建空白文档(建议:90x300px) 录制动作,alt+F9   上图中,可以新建分组前端,再新建动作 ...

  3. 《ArcGIS Runtime SDK for Android开发笔记》——问题集:使用TextSymbol做标注显示乱码

    1.前言 在14年的时候写过一篇博客关于ArcGIS for Android 10.1.1API 中文标注导致程序异常崩溃问题,但是当时并没有很好的解决这样一个问题,也并没有深入研究分析这样的一个异常 ...

  4. Navicat for MySQL导入文件

    1.导入SQL文件超出Navicat限制时,需要设置其限制的大小(具体看SQL文件大小) 打开Navicat For MySQL的命令行界面,输入: set global max_allowed_pa ...

  5. php的yii框架开发总结4

    用户验证的实现:/protected/components/UserIdentity.php 修改:function authenticate()函数中的语句 public function auth ...

  6. 笨办法学Python(六)

    习题 6: 字符串(string)和文本 虽然你已经在程序中写过字符串了,你还没学过它们的用处.在这章习题中我们将使用复杂的字符串来建立一系列的变量,从中你将学到它们的用途.首先我们解释一下字符串是什 ...

  7. May 04th 2017 Week 18th Thursday

    No matter how far you may fly, never forget where you come from. 无论你能飞多远,都别忘了你来自何方. I never forget w ...

  8. 爬虫第一篇基本库的使用——urllib

    在Python2中有urllib2和urllib3两个库来实现请求的发送,在Pyhon3中则统一为urllib. urilib包含以下4个模块 request:最基本的请求模块,可以用来实现请求的发送 ...

  9. pc/移动端(手机端)浏览器的直播rtmp hls(适合入门者快速上手)

    一.直播概述 关于直播,大概的过程是:推流端——>源站——>客户端拉流,用媒介播放 客户端所谓的拉流就是一个播放的地址url,会有多种类型的流: 视频直播服务目前支持三种直播协议,分别是R ...

  10. DOM笔记(十三):JavaScript的继承方式

    在Java.C++.C#等OO语言中,都支持两种继承方式:接口继承和实现继承.接口继承制继承方法签名,实现继承则继承实际的方法和属性.在SCMAScript中,由于函数没有签名,所以无法实现接口继承, ...