Dapper代码引入到项目中

master
xiaochanghai 1 year ago
parent c8853da9a1
commit 5c0d3e6483
  1. BIN
      Lib/SimpleDapper.dll
  2. 6
      Model/Tiobon.Web.pdm
  3. 2
      Tiobon.Core.Api/Program.cs
  4. 7
      Tiobon.Core.Api/Tiobon.Core.Api.csproj
  5. 77
      Tiobon.Core.Api/Tiobon.Core.xml
  6. 6
      Tiobon.Core.Common/DB/Dapper/BaseProvider/ServerMapPath/IDependency.cs
  7. 50
      Tiobon.Core.Common/DB/Dapper/BaseProvider/ServerMapPath/PathProvider.cs
  8. 164
      Tiobon.Core.Common/DB/Dapper/Configuration/AppSetting.cs
  9. 6
      Tiobon.Core.Common/DB/Dapper/Const/DataBaseType.cs
  10. 23
      Tiobon.Core.Common/DB/Dapper/Const/SqlDbTypeName.cs
  11. 151
      Tiobon.Core.Common/DB/Dapper/DBManager/BaseDBConfig.cs
  12. 8
      Tiobon.Core.Common/DB/Dapper/DBManager/DBConnectionAttribute.cs
  13. 138
      Tiobon.Core.Common/DB/Dapper/DBManager/DBServerProvider.cs
  14. 38
      Tiobon.Core.Common/DB/Dapper/Entity/EntityAttribute.cs
  15. 13
      Tiobon.Core.Common/DB/Dapper/Enums/DbCurrentType.cs
  16. 9
      Tiobon.Core.Common/DB/Dapper/Extensions/AutofacManager/AutofacContainerModule.cs
  17. 620
      Tiobon.Core.Common/DB/Dapper/Extensions/EntityProperties.cs
  18. 61
      Tiobon.Core.Common/DB/Dapper/Extensions/GenericExtension.cs
  19. 67
      Tiobon.Core.Common/DB/Dapper/Extensions/LambdaExtensions.cs
  20. 21
      Tiobon.Core.Common/DB/Dapper/Extensions/MethodInfoExtensions.cs
  21. 31
      Tiobon.Core.Common/DB/Dapper/Extensions/ServerExtension.cs
  22. 18
      Tiobon.Core.Common/DB/Dapper/Extensions/ServiceProviderManagerExtension.cs
  23. 14
      Tiobon.Core.Common/DB/Dapper/Extensions/SimpleDapperSetup.cs
  24. 117
      Tiobon.Core.Common/DB/Dapper/Extensions/StringExtension.cs
  25. 121
      Tiobon.Core.Common/DB/Dapper/ISqlDapper.cs
  26. 105
      Tiobon.Core.Common/DB/Dapper/ITransDapper.cs
  27. 29
      Tiobon.Core.Common/DB/Dapper/SimpleDapper.csproj
  28. 665
      Tiobon.Core.Common/DB/Dapper/SqlDapper.cs
  29. 495
      Tiobon.Core.Common/DB/Dapper/TransDapper.cs
  30. 153
      Tiobon.Core.Common/DB/Dapper/Utilities/DbAccess.cs
  31. 83
      Tiobon.Core.Common/DB/Dapper/Utilities/FileHelper.cs
  32. 15
      Tiobon.Core.Common/DB/Dapper/Utilities/HttpContext.cs
  33. 15
      Tiobon.Core.Common/DB/Dapper/Utilities/StringHelper.cs
  34. 33
      Tiobon.Core.Common/DB/Dapper/Utilities/UtilConvert.cs
  35. 9
      Tiobon.Core.Common/DB/DbSql/DbInsert.cs
  36. 2
      Tiobon.Core.Common/Seed/FrameSeed.cs
  37. 11
      Tiobon.Core.Common/Tiobon.Core.Common.csproj
  38. 2
      Tiobon.Core.Tests/Common_Test/DbAccess_Should.cs
  39. 6
      Tiobon.Core.Tests/Tiobon.Core.Tests.csproj

Binary file not shown.

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<?PowerDesigner AppLocale="UTF16" ID="{C294868A-C3F3-41AD-98CC-78B6D4E0CC40}" Label="" LastModificationDate="1713342927" Name="一优开发平台" Objects="6510" Symbols="279" Target="Microsoft SQL Server 2008" Type="{CDE44E21-9669-11D1-9914-006097355D9B}" signature="PDM_DATA_MODEL_XML" version="15.0.0.2613"?>
<?PowerDesigner AppLocale="UTF16" ID="{C294868A-C3F3-41AD-98CC-78B6D4E0CC40}" Label="" LastModificationDate="1713343323" Name="一优开发平台" Objects="6510" Symbols="279" Target="Microsoft SQL Server 2008" Type="{CDE44E21-9669-11D1-9914-006097355D9B}" signature="PDM_DATA_MODEL_XML" version="15.0.0.2613"?>
<!-- do not edit this file -->
<Model xmlns:a="attribute" xmlns:c="collection" xmlns:o="object">
@ -105116,8 +105116,8 @@ Shadow=0</a:DisplayPreferences>
</o:ReferenceSymbol>
<o:TableSymbol Id="o6310">
<a:CreationDate>1630077158</a:CreationDate>
<a:ModificationDate>1713342688</a:ModificationDate>
<a:Rect>((-18861,2845), (-12775,6445))</a:Rect>
<a:ModificationDate>1713343323</a:ModificationDate>
<a:Rect>((-6725,2913), (-639,6513))</a:Rect>
<a:AutoAdjustToText>0</a:AutoAdjustToText>
<a:LineColor>16711680</a:LineColor>
<a:FillColor>16744448</a:FillColor>

@ -9,7 +9,7 @@ using Microsoft.IdentityModel.Logging;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Serilog;
using SimpleDapper.Extensions;
using Tiobon.Core.Common.DB.Dapper.Extensions;
using Tiobon.Core;
using Tiobon.Core.Common.Core;
using Tiobon.Core.Extensions;

@ -53,7 +53,6 @@
<None Remove="wwwroot\ui\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Controllers\BlogController.cs" />
<Compile Remove="Controllers\DepartmentController.cs" />
<Compile Remove="Controllers\HealthCheckController.cs" />
<Compile Remove="Controllers\ImgController.cs" />
@ -140,12 +139,6 @@
<ProjectReference Include="..\Tiobon.Core.Extensions\Tiobon.Core.Extensions.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="SimpleDapper">
<HintPath>..\Lib\SimpleDapper.dll</HintPath>
</Reference>
</ItemGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties appsettings_1json__JsonSchema="" />

@ -72,6 +72,83 @@
<param name="parameters"></param>
<returns></returns>
</member>
<member name="T:Tiobon.Core.Controllers.TiobonController">
<summary>
博客管理
</summary>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.#ctor(Microsoft.Extensions.Logging.ILogger{Tiobon.Core.Controllers.TiobonController})">
<summary>
构造函数
</summary>
<param name="logger"></param>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.Get(System.Int32,System.Int32,System.String,System.String)">
<summary>
获取博客列表【无权限】
</summary>
<param name="id"></param>
<param name="page"></param>
<param name="bcategory"></param>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.Get(System.Int64)">
<summary>
获取博客详情
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.DetailNuxtNoPer(System.Int64)">
<summary>
获取详情【无权限】
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.V2_Tiobontest">
<summary>
获取博客测试信息 v2版本
</summary>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.Post(Tiobon.Core.Model.Models.TiobonArticle)">
<summary>
添加博客【无权限】
</summary>
<param name="TiobonArticle"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.AddForMVP(Tiobon.Core.Model.Models.TiobonArticle)">
<summary>
</summary>
<param name="TiobonArticle"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.Put(Tiobon.Core.Model.Models.TiobonArticle)">
<summary>
更新博客信息
</summary>
<param name="TiobonArticle"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.Delete(System.Int64)">
<summary>
删除博客
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.TiobonController.ApacheTestUpdate">
<summary>
apache jemeter 压力测试
更新接口
</summary>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.DbFirstController.#ctor(SqlSugar.ISqlSugarClient,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary>
构造函数

@ -0,0 +1,6 @@
namespace Tiobon.Core.Common.DB.Dapper.BaseProvider.ServerMapPath
{
public interface IDependency
{
}
}

@ -0,0 +1,50 @@

using Microsoft.AspNetCore.Hosting;
using System.IO;
using Tiobon.Core.Common.DB.Dapper.Extensions;
namespace Tiobon.Core.Common.DB.Dapper.BaseProvider.ServerMapPath;
public interface IPathProvider : IDependency
{
string MapPath(string path);
string MapPath(string path, bool rootPath);
IWebHostEnvironment GetHostingEnvironment();
}
public class PathProvider : IPathProvider
{
private IWebHostEnvironment _hostingEnvironment;
public PathProvider(IWebHostEnvironment environment)
{
_hostingEnvironment = environment;
}
public IWebHostEnvironment GetHostingEnvironment()
{
return _hostingEnvironment;
}
public string MapPath(string path)
{
return MapPath(path, false);
}
/// <summary>
///
/// </summary>
/// <param name="path"></param>
/// <param name="rootPath">获取wwwroot路径</param>
/// <returns></returns>
public string MapPath(string path, bool rootPath)
{
if (rootPath)
{
if (_hostingEnvironment.WebRootPath == null)
{
_hostingEnvironment.WebRootPath = _hostingEnvironment.ContentRootPath + "/wwwroot".ReplacePath();
}
return Path.Combine(_hostingEnvironment.WebRootPath, path).ReplacePath();
}
return Path.Combine(_hostingEnvironment.ContentRootPath, path).ReplacePath();
}
}

@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.DependencyInjection;
using Tiobon.Core.Common.DB.Dapper.DBManager;
using Tiobon.Core.Common.DB.Dapper.Enums;
namespace Tiobon.Core.Common.DB.Dapper;
public static class AppSetting
{
public static IConfiguration Configuration { get; private set; }
public static string DbConnectionString { get; private set; }
public static string DBType { get; private set; }
private static ConnectionStrings _connection;
public static void Init()
{
Configuration = new ConfigurationBuilder()
.Add(new JsonConfigurationSource { Path = "appsettings.json", ReloadOnChange = true })
.Build(); ;
//var baseDirectory = AppContext.BaseDirectory;
//var provider = services.BuildServiceProvider();
////设置修改或删除时需要设置为默认用户信息的字段
//CreateMember = provider.GetRequiredService<IOptions<CreateMember>>().Value ?? new CreateMember();
//ModifyMember = provider.GetRequiredService<IOptions<ModifyMember>>().Value ?? new ModifyMember();
#region 初始化数据库
MainDb.CurrentDbConnId = app("MainDB");
var mainConnetctDb = BaseDBConfig.MutiConnectionString.allDbs.Find(x => x.ConnId == MainDb.CurrentDbConnId);
Const.DBType.Name = DataBaseType.SqlServer.ToString();
DBType = DataBaseType.SqlServer.ToString();
try
{
DbConnectionString = mainConnetctDb.Connection;
}
catch { }
if (string.IsNullOrEmpty(DbConnectionString))
throw new Exception("未配置好数据库默认连接");
#region 检查服务是否可用
//bool mysql = Const.DBType.Name == DbCurrentType.MySql.ToString();
//if (mysql)
//{
//}
bool mssql = Const.DBType.Name == DbCurrentType.MsSql.ToString();
if (mssql)
{
using var conn = new SqlConnection(_connection.DbConnectionString);
while (true)
{
//if (Utility.IsPortOpen(conn.DataSource, 1433))
//{
// Logger.WriteLog("[数据库] 服务状态正常");
// break;
//}
//else
//{
// Logger.WriteLog("[数据库] 服务状态异常, 稍后重试");
// System.Threading.Thread.Sleep(5000);
//}
//conn.Open();
//if (conn.State == ConnectionState.Open)
//{
// conn.Close();
// Logger.WriteLog("[数据库] 服务状态正常");
// break;
//}
//else
//{
// Logger.WriteLog("[数据库] 服务状态异常, 等待 5 秒后重试");
// System.Threading.Thread.Sleep(5000);
//}
}
}
#endregion
#endregion
}
// 多个节点name格式 :["key:key1"]
public static string GetSettingString(string key)
{
return Configuration[key];
}
// 多个节点,通过.GetSection("key")["key1"]获取
public static IConfigurationSection GetSection(string key)
{
return Configuration.GetSection(key);
}
/// <summary>
/// 封装要操作的字符
/// </summary>
/// <param name="sections">节点配置</param>
/// <returns></returns>
public static string app(params string[] sections)
{
try
{
if (sections.Any())
{
return Configuration[string.Join(":", sections)];
}
}
catch (Exception) { }
return "";
}
/// <summary>
/// 递归获取配置信息数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sections"></param>
/// <returns></returns>
public static List<T> app<T>(params string[] sections)
{
List<T> list = new List<T>();
// 引用 Microsoft.Extensions.Configuration.Binder 包
Configuration.Bind(string.Join(":", sections), list);
return list;
}
}
#region 数据库链接
/// <summary>
/// 数据库链接
/// </summary>
public class ConnectionStrings
{
/// <summary>
/// 数据库类型
/// </summary>
public string DBType { get; set; }
/// <summary>
/// 数据库链接字符串
/// </summary>
public string DbConnectionString { get; set; }
}
#endregion

@ -0,0 +1,6 @@
namespace Tiobon.Core.Common.DB.Dapper.Const;
public static class DBType
{
public static string Name { get; set; }
}

@ -0,0 +1,23 @@
namespace Tiobon.Core.Common.DB.Dapper;
public struct SqlDbTypeName
{
public const string NVarChar = "nvarchar";
public const string VarChar = "varchar";
public const string NChar = "nchar";
public const string Char = "char";
public const string Text = "text";
public const string Int = "int";
public const string BigInt = "bigint";
public const string DateTime = "datetime";
public const string Date = "date";
public const string SmallDateTime = "smalldatetime";
public const string SmallDate = "smalldate";
public const string Float = "float";
public const string Decimal = "decimal";
public const string Double = "double";
public const string Bit = "bit";
public const string Bool = "bool";
public const string UniqueIdentifier = "uniqueidentifier";
}

@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SqlSugar;
namespace Tiobon.Core.Common.DB.Dapper.DBManager;
public class BaseDBConfig
{
/* GitHub的历史记录
* AppSetting.json设置为true的第一个db连接
*/
public static (List<MutiDBOperate> allDbs, List<MutiDBOperate> slaveDbs) MutiConnectionString => MutiInitConn();
private static string DifDBConnOfSecurity(params string[] conn)
{
foreach (var item in conn)
{
try
{
if (File.Exists(item))
{
return File.ReadAllText(item).Trim();
}
}
catch (System.Exception)
{
}
}
return conn[conn.Length - 1];
}
public static (List<MutiDBOperate>, List<MutiDBOperate>) MutiInitConn()
{
List<MutiDBOperate> listdatabase = AppSetting.app<MutiDBOperate>("DBS")
.Where(i => i.Enabled).ToList();
foreach (var i in listdatabase)
{
SpecialDbString(i);
}
List<MutiDBOperate> listdatabaseSimpleDB = new List<MutiDBOperate>(); //单库
List<MutiDBOperate> listdatabaseSlaveDB = new List<MutiDBOperate>(); //从库
// 单库,且不开启读写分离,只保留一个
if (!AppSetting.app(new string[] { "CQRSEnabled" }).ObjToBool() && !AppSetting.app(new string[] { "MutiDBEnabled" }).ObjToBool())
{
if (listdatabase.Count == 1)
{
return (listdatabase, listdatabaseSlaveDB);
}
else
{
var dbFirst = listdatabase.FirstOrDefault(d => d.ConnId == AppSetting.app(new string[] { "MainDB" }).ObjToString());
if (dbFirst == null)
{
dbFirst = listdatabase.FirstOrDefault();
}
listdatabaseSimpleDB.Add(dbFirst);
return (listdatabaseSimpleDB, listdatabaseSlaveDB);
}
}
// 读写分离,且必须是单库模式,获取从库
if (AppSetting.app(new string[] { "CQRSEnabled" }).ObjToBool() && !AppSetting.app(new string[] { "MutiDBEnabled" }).ObjToBool())
{
if (listdatabase.Count > 1)
{
listdatabaseSlaveDB = listdatabase.Where(d => d.ConnId != AppSetting.app(new string[] { "MainDB" }).ObjToString()).ToList();
}
}
return (listdatabase, listdatabaseSlaveDB);
//}
}
/// <summary>
/// 定制Db字符串
/// 目的是保证安全:优先从本地txt文件获取,若没有文件则从AppSetting.json中获取
/// </summary>
/// <param name="mutiDBOperate"></param>
/// <returns></returns>
private static MutiDBOperate SpecialDbString(MutiDBOperate mutiDBOperate)
{
if (mutiDBOperate.DbType == DataBaseType.Sqlite)
{
mutiDBOperate.Connection = $"DataSource=" + Path.Combine(Environment.CurrentDirectory, mutiDBOperate.Connection);
}
else if (mutiDBOperate.DbType == DataBaseType.SqlServer)
{
mutiDBOperate.Connection = DifDBConnOfSecurity(@"D:\my-file\dbCountPsw1_SqlserverConn.txt", mutiDBOperate.Connection);
}
else if (mutiDBOperate.DbType == DataBaseType.MySql)
{
mutiDBOperate.Connection = DifDBConnOfSecurity(@"D:\my-file\dbCountPsw1_MySqlConn.txt", mutiDBOperate.Connection);
}
else if (mutiDBOperate.DbType == DataBaseType.Oracle)
{
mutiDBOperate.Connection = DifDBConnOfSecurity(@"D:\my-file\dbCountPsw1_OracleConn.txt", mutiDBOperate.Connection);
}
return mutiDBOperate;
}
}
public enum DataBaseType
{
MySql = 0,
SqlServer = 1,
Sqlite = 2,
Oracle = 3,
PostgreSQL = 4,
Dm = 5,
Kdbndp = 6,
}
public class MutiDBOperate
{
/// <summary>
/// 连接启用开关
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// 连接ID
/// </summary>
public string ConnId { get; set; }
/// <summary>
/// 从库执行级别,越大越先执行
/// </summary>
public int HitRate { get; set; }
/// <summary>
/// 连接字符串
/// </summary>
public string Connection { get; set; }
/// <summary>
/// 数据库类型
/// </summary>
public DataBaseType DbType { get; set; }
}

@ -0,0 +1,8 @@
using System;
namespace Tiobon.Core.Common.DB.Dapper.DBManager;
public class DBConnectionAttribute : Attribute
{
public string DBName { get; set; }
}

@ -0,0 +1,138 @@
//using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Tiobon.Core.Common.DB.Dapper.Const;
using Tiobon.Core.Common.DB.Dapper;
using Tiobon.Core.Common.DB.Dapper.Enums;
using Tiobon.Core.Common.DB.Dapper.Extensions;
namespace Tiobon.Core.Common.DB.Dapper.DBManager;
public class DBServerProvider
{
private static Dictionary<string, string> ConnectionPool = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public static string DefaultConnName = "defalut";
static DBServerProvider()
{
SetConnection(DefaultConnName, AppSetting.DbConnectionString);
}
public static void SetConnection(string key, string val)
{
if (ConnectionPool.ContainsKey(key))
{
ConnectionPool[key] = val;
return;
}
ConnectionPool.Add(key, val);
}
/// <summary>
/// 设置默认数据库连接
/// </summary>
/// <param name="val"></param>
public static void SetDefaultConnection(string val)
{
SetConnection(DefaultConnName, val);
}
public static string GetConnectionString(string key)
{
key = key ?? DefaultConnName;
if (ConnectionPool.ContainsKey(key))
{
return ConnectionPool[key];
}
return key;
}
/// <summary>
/// 获取默认数据库连接
/// </summary>
/// <returns></returns>
public static string GetConnectionString()
{
return GetConnectionString(DefaultConnName);
}
//private static bool _isMysql = DBType.Name == DbCurrentType.MySql.ToString();
private static bool _isMysql = false;
public static IDbConnection GetDbConnection(string connString = null)
{
if (_isMysql)
{
return new MySql.Data.MySqlClient.MySqlConnection(connString ?? ConnectionPool[DefaultConnName]);
}
return new SqlConnection(connString ?? ConnectionPool[DefaultConnName]);
}
public static IDbConnection GetMyDbConnection(string connString = null)
{
//new MySql.Data.MySqlClient.MySqlConnection(connString);
string mySql = "Data Source=132.232.2.109;Database=mysql;User ID=xx;Password=xxx;pooling=true;CharSet=utf8;port=3306;sslmode=none";
// MySqlConnector
return new MySql.Data.MySqlClient.MySqlConnection(mySql);
}
//public static VOLContext DbContext
//{
// get { return GetEFDbContext(); }
//}
//public static VOLContext GetEFDbContext()
//{
// return GetEFDbContext(null);
//}
//public static VOLContext GetEFDbContext(string dbName)
//{
// VOLContext beefContext = Utilities.HttpContext.Current.RequestServices.GetService(typeof(VOLContext)) as VOLContext;
// if (dbName != null)
// {
// if (!ConnectionPool.ContainsKey(dbName))
// {
// throw new Exception("数据库连接名称错误");
// }
// beefContext.Database.GetDbConnection().ConnectionString = ConnectionPool[dbName];
// }
// return beefContext;
//}
//public static void SetDbContextConnection(VOLContext beefContext, string dbName)
//{
// if (!ConnectionPool.ContainsKey(dbName))
// {
// throw new Exception("数据库连接名称错误");
// }
// beefContext.Database.GetDbConnection().ConnectionString = ConnectionPool[dbName];
//}
/// <summary>
/// 获取实体的数据库连接
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="defaultDbContext"></param>
/// <returns></returns>
//public static void GetDbContextConnection<TEntity>(VOLContext defaultDbContext)
//{
// //string connstr= defaultDbContext.Database.GetDbConnection().ConnectionString;
// // if (connstr != ConnectionPool[DefaultConnName])
// // {
// // defaultDbContext.Database.GetDbConnection().ConnectionString = ConnectionPool[DefaultConnName];
// // };
//}
public static ISqlDapper SqlDapper
{
get
{
return new SqlDapper(DefaultConnName);
}
}
public static ISqlDapper GetSqlDapper(string dbName = null)
{
return new SqlDapper(dbName ?? DefaultConnName);
}
public static ISqlDapper GetSqlDapper<TEntity>()
{
//获取实体真实的数据库连接池对象名,如果不存在则用默认数据连接池名
string dbName = typeof(TEntity).GetTypeCustomValue<DBConnectionAttribute>(x => x.DBName) ?? DefaultConnName;
return GetSqlDapper(dbName);
}
}

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tiobon.Core.Common.DB.Dapper.Entity
{
public class EntityAttribute : Attribute
{
/// <summary>
/// 真实表名(数据库表名,若没有填写默认实体为表名)
/// </summary>
public string TableName { get; set; }
/// <summary>
/// 表中文名
/// </summary>
public string TableCnName { get; set; }
/// <summary>
/// 子表
/// </summary>
public Type[] DetailTable { get; set; }
/// <summary>
/// 子表中文名
/// </summary>
public string DetailTableCnName { get; set; }
/// <summary>
/// 数据库
/// </summary>
public string DBServer { get; set; }
//是否开启用户数据权限,true=用户只能操作自己(及下级角色)创建的数据,如:查询、删除、修改等操作
public bool CurrentUserPermission { get; set; }
public Type ApiInput { get; set; }
public Type ApiOutput { get; set; }
}
}

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Tiobon.Core.Common.DB.Dapper.Enums
{
public enum DbCurrentType
{
MySql = 1,
MsSql = 2,
PgSql = 3
}
}

@ -0,0 +1,9 @@
namespace Tiobon.Core.Common.DB.Dapper.Extensions.AutofacManager;
public class AutofacContainerModule
{
public static TService GetService<TService>() where TService:class
{
return typeof(TService).GetService() as TService;
}
}

@ -0,0 +1,620 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using Tiobon.Core.Common.DB.Dapper.Entity;
namespace Tiobon.Core.Common.DB.Dapper.Extensions;
public static class EntityProperties
{
/// <summary>
/// 获取对象里指定成员名称
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="properties"> 格式 Expression<Func<entityt, object>> exp = x => new { x.字段1, x.字段2 };或x=>x.Name</param>
/// <returns></returns>
public static string[] GetExpressionProperty<TEntity>(this Expression<Func<TEntity, object>> properties)
{
if (properties == null)
return new string[] { };
if (properties.Body is NewExpression)
return ((NewExpression)properties.Body).Members.Select(x => x.Name).ToArray();
if (properties.Body is MemberExpression)
return new string[] { ((MemberExpression)properties.Body).Member.Name };
if (properties.Body is UnaryExpression)
return new string[] { ((properties.Body as UnaryExpression).Operand as MemberExpression).Member.Name };
throw new Exception("未实现的表达式");
}
public static Dictionary<string, string> GetColumType(this PropertyInfo[] properties, bool containsKey)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (PropertyInfo property in properties)
{
//if (!containsKey && property.IsKey())
//{
// continue;
//}
var keyVal = GetColumnType(property, true);
dictionary.Add(keyVal.Key, keyVal.Value);
}
return dictionary;
}
private static readonly Dictionary<Type, string> entityMapDbColumnType = new Dictionary<Type, string>() {
{typeof(int),SqlDbTypeName.Int },
{typeof(int?),SqlDbTypeName.Int },
{typeof(long),SqlDbTypeName.BigInt },
{typeof(long?),SqlDbTypeName.BigInt },
{typeof(decimal),"decimal(18, 5)" },
{typeof(decimal?),"decimal(18, 5)" },
{typeof(double),"decimal(18, 5)" },
{typeof(double?),"decimal(18, 5)" },
{typeof(float),"decimal(18, 5)" },
{typeof(float?),"decimal(18, 5)" },
{typeof(Guid),"UniqueIdentifier" },
{typeof(Guid?),"UniqueIdentifier" },
{typeof(byte),"tinyint" },
{typeof(byte?),"tinyint" },
{typeof(string),"nvarchar" }
};
/// <summary>
/// 返回属性的字段及数据库类型
/// </summary>
/// <param name="property"></param>
/// <param name="lenght">是否包括后字段具体长度:nvarchar(100)</param>
/// <returns></returns>
public static KeyValuePair<string, string> GetColumnType(this PropertyInfo property, bool lenght = false)
{
string colType = "";
object objAtrr = property.GetTypeCustomAttributes(typeof(ColumnAttribute), out bool asType);
if (asType)
{
colType = ((ColumnAttribute)objAtrr).TypeName.ToLower();
if (!string.IsNullOrEmpty(colType))
{
//不需要具体长度直接返回
if (!lenght)
{
return new KeyValuePair<string, string>(property.Name, colType);
}
if (colType == "decimal" || colType == "double" || colType == "float")
{
objAtrr = property.GetTypeCustomAttributes(typeof(DisplayFormatAttribute), out asType);
colType += "(" + (asType ? ((DisplayFormatAttribute)objAtrr).DataFormatString : "18,5") + ")";
}
///如果是string,根据 varchar或nvarchar判断最大长度
if (property.PropertyType.ToString() == "System.String")
{
colType = colType.Split("(")[0];
objAtrr = property.GetTypeCustomAttributes(typeof(MaxLengthAttribute), out asType);
if (asType)
{
int length = ((MaxLengthAttribute)objAtrr).Length;
colType += "(" + (length < 1 || length > (colType.StartsWith("n") ? 8000 : 4000) ? "max" : length.ToString()) + ")";
}
else
{
colType += "(max)";
}
}
return new KeyValuePair<string, string>(property.Name, colType);
}
}
if (entityMapDbColumnType.TryGetValue(property.PropertyType, out string value))
{
colType = value;
}
else
{
colType = SqlDbTypeName.NVarChar;
}
if (lenght && colType == SqlDbTypeName.NVarChar)
{
colType = "nvarchar(max)";
}
return new KeyValuePair<string, string>(property.Name, colType);
}
/// <summary>
///<param name="sql">要执行的sql语句如:通过EntityToSqlTempName.Temp_Insert0.ToString()字符串占位,生成的的sql语句会把EntityToSqlTempName.Temp_Insert0.ToString()替换成生成的sql临时表数据
/// string sql = " ;DELETE FROM " + typeEntity.Name + " where " + typeEntity.GetKeyName() +
/// " in (select * from " + EntityToSqlTempName.Temp_Insert0.ToString() + ")";
/// </param>
/// </summary>
/// <param name="array"></param>
/// <param name="fieldType">指定生成的数组值的类型</param>
/// <param name="sql"></param>
/// <returns></returns>
public static string GetArraySql(this object[] array, FieldType fieldType, string sql)
{
if (array == null || array.Count() == 0)
{
return string.Empty;
}
string columnType = string.Empty;
List<ArrayEntity> arrrayEntityList = array.Select(x => new ArrayEntity { column1 = x.ToString() }).ToList();
return arrrayEntityList.GetEntitySql(false, sql, null, null, fieldType);
}
/// <summary>
/// 根据实体获取key的类型,用于update或del操作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static FieldType GetFieldType(this Type typeEntity)
{
FieldType fieldType;
string columnType = typeEntity.GetProperties().Where(x => x.Name == typeEntity.GetKeyName()).ToList()[0].GetColumnType(false).Value;
switch (columnType)
{
case SqlDbTypeName.Int: fieldType = FieldType.Int; break;
case SqlDbTypeName.BigInt: fieldType = FieldType.BigInt; break;
case SqlDbTypeName.VarChar: fieldType = FieldType.VarChar; break;
case SqlDbTypeName.UniqueIdentifier: fieldType = FieldType.UniqueIdentifier; break;
default: fieldType = FieldType.NvarChar; break;
}
return fieldType;
}
public static string GetEntitySql<T>(this IEnumerable<T> entityList,
bool containsKey = false,
string sql = null,
Expression<Func<T, object>> ignoreFileds = null,
Expression<Func<T, object>> fixedColumns = null,
FieldType? fieldType = null
)
{
if (entityList == null || entityList.Count() == 0) return "";
PropertyInfo[] propertyInfo = typeof(T).GetProperties().ToArray();
if (propertyInfo.Count() == 0)
{
propertyInfo = entityList.ToArray()[0].GetType().GetGenericProperties().ToArray();
}
propertyInfo = propertyInfo.GetGenericProperties().ToArray();
string[] arr = null;
if (fixedColumns != null)
{
arr = fixedColumns.GetExpressionToArray();
PropertyInfo keyProperty = typeof(T).GetKeyProperty();
propertyInfo = propertyInfo.Where(x => (containsKey && x.Name == keyProperty.Name) || arr.Contains(x.Name)).ToArray();
}
if (ignoreFileds != null)
{
arr = ignoreFileds.GetExpressionToArray();
propertyInfo = propertyInfo.Where(x => !arr.Contains(x.Name)).ToArray();
}
Dictionary<string, string> dictProperties = propertyInfo.GetColumType(containsKey);
if (fieldType != null)
{
string realType = fieldType.ToString();
if ((int)fieldType == 0 || (int)fieldType == 1)
{
realType += "(max)";
}
dictProperties = new Dictionary<string, string> { { dictProperties.Select(x => x.Key).ToList()[0], realType } };
}
if (dictProperties.Keys.Count * entityList.Count() > 50 * 3000)
{
throw new Exception("写入数据太多,请分开写入。");
}
string cols = string.Join(",", dictProperties.Select(c => "[" + c.Key + "]" + " " + c.Value));
StringBuilder declareTable = new StringBuilder();
string tempTablbe = "#" + EntityToSqlTempName.TempInsert.ToString();
declareTable.Append("CREATE TABLE " + tempTablbe + " (" + cols + ")");
declareTable.Append("\r\n");
//参数总数量
int parCount = (dictProperties.Count) * (entityList.Count());
int takeCount = 0;
int maxParsCount = 2050;
if (parCount > maxParsCount)
{
//如果参数总数量超过2100,设置每次分批循环写入表的大小
takeCount = maxParsCount / dictProperties.Count;
}
int count = 0;
StringBuilder stringLeft = new StringBuilder();
StringBuilder stringCenter = new StringBuilder();
StringBuilder stringRight = new StringBuilder();
int index = 0;
foreach (T entity in entityList)
{
//每1000行需要分批写入(数据库限制每批至多写入1000行数据)
if (index == 0 || index >= 1000 || takeCount - index == 0)
{
if (stringLeft.Length > 0)
{
declareTable.AppendLine(
stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() +
stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() +
stringRight.Remove(stringRight.Length - 1, 1).ToString());
stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear();
}
stringLeft.AppendLine("exec sp_executesql N'SET NOCOUNT ON;");
stringCenter.Append("N'");
index = 0; count = 0;
}
stringLeft.Append(index == 0 ? "; INSERT INTO " + tempTablbe + " values (" : " ");
index++;
foreach (PropertyInfo property in propertyInfo)
{
//if (!containsKey && property.IsKey()) { continue; }
string par = "@v" + count;
stringLeft.Append(par + ",");
stringCenter.Append(par + " " + dictProperties[property.Name] + ",");
object val = property.GetValue(entity);
if (val == null)
{
stringRight.Append(par + "=NUll,");
}
else
{
stringRight.Append(par + "='" + val.ToString().Replace("'", "''''") + "',");
}
count++;
}
stringLeft.Remove(stringLeft.Length - 1, 1);
stringLeft.Append("),(");
}
if (stringLeft.Length > 0)
{
declareTable.AppendLine(
stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() +
stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() +
stringRight.Remove(stringRight.Length - 1, 1).ToString());
stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear();
}
if (!string.IsNullOrEmpty(sql))
{
sql = sql.Replace(EntityToSqlTempName.TempInsert.ToString(), tempTablbe);
declareTable.AppendLine(sql);
}
else
{
declareTable.AppendLine(" SELECT " + (string.Join(",", fixedColumns?.GetExpressionToArray() ?? new string[] { "*" })) + " FROM " + tempTablbe);
}
if (tempTablbe.Substring(0, 1) == "#")
{
declareTable.AppendLine("; drop table " + tempTablbe);
}
return declareTable.ToString();
}
public static string GetKeyName(this Type typeinfo)
{
return typeinfo.GetProperties().GetKeyName();
}
public static string GetKeyName(this PropertyInfo[] properties)
{
return properties.GetKeyName(false);
}
/// <summary>
/// 获取key列名
/// </summary>
/// <param name="properties"></param>
/// <param name="keyType">true获取key对应类型,false返回对象Key的名称</param>
/// <returns></returns>
public static string GetKeyName(this PropertyInfo[] properties, bool keyType)
{
string keyName = string.Empty;
foreach (PropertyInfo propertyInfo in properties)
{
if (!propertyInfo.IsKey())
continue;
if (!keyType)
return propertyInfo.Name;
var attributes = propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), false);
//如果没有ColumnAttribute的需要单独再验证,下面只验证有属性的
if (attributes.Length > 0)
return ((ColumnAttribute)attributes[0]).TypeName.ToLower();
else
return GetColumType(new PropertyInfo[] { propertyInfo }, true)[propertyInfo.Name];
}
return keyName;
}
/// <summary>
/// 获取主键字段
/// </summary>
/// <param name="propertyInfo"></param>
/// <returns></returns>
public static PropertyInfo GetKeyProperty(this Type entity)
{
return entity.GetProperties().GetKeyProperty();
}
public static PropertyInfo GetKeyProperty(this PropertyInfo[] properties)
{
return properties.Where(c => c.IsKey()).FirstOrDefault();
}
public static bool IsKey(this PropertyInfo propertyInfo)
{
object[] keyAttributes = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), false);
if (keyAttributes.Length > 0)
return true;
return false;
}
/// <summary>
/// 判断是否包含某个属性:
/// 如 [Editable(true)]
// public string MO { get; set; }包含Editable
/// </summary>
/// <param name="propertyInfo"></param>
/// <param name="type"></param>
/// <returns></returns>
public static bool ContainsCustomAttributes(this PropertyInfo propertyInfo, Type type)
{
propertyInfo.GetTypeCustomAttributes(type, out bool contains);
return contains;
}
/// <summary>
/// 获取PropertyInfo指定属性
/// </summary>
/// <param name="propertyInfo"></param>
/// <param name="type"></param>
/// <returns></returns>
public static object GetTypeCustomAttributes(this PropertyInfo propertyInfo, Type type, out bool asType)
{
object[] attributes = propertyInfo.GetCustomAttributes(type, false);
if (attributes.Length == 0)
{
asType = false;
return new string[0];
}
asType = true;
return attributes[0];
}
/// <summary>
/// 验证数据库字段类型与值是否正确,
/// </summary>
/// <param name="propertyInfo">propertyInfo为当字段,当前字段必须有ColumnAttribute属性,
/// 如字段:标识为数据库int类型[Column(TypeName="int")] public int Id { get; set; }
/// 如果是小数float或Decimal必须对propertyInfo字段加DisplayFormatAttribute属性
/// </param>
/// <param name="value"></param>
/// <returns>IEnumerable<(bool, string, object)> bool成否校验成功,string校验失败信息,object,当前校验的值</returns>
public static IEnumerable<(bool, string, object)> ValidationValueForDbType(this PropertyInfo propertyInfo, params object[] values)
{
string dbTypeName = propertyInfo.GetTypeCustomValue<ColumnAttribute>(c => c.TypeName);
foreach (object value in values)
{
yield return dbTypeName.ValidationVal(value, propertyInfo);
}
}
private static readonly Dictionary<Type, string> ProperWithDbType = new Dictionary<Type, string>() {
{ typeof(string),SqlDbTypeName.NVarChar },
{ typeof(DateTime),SqlDbTypeName.DateTime},
{typeof(long),SqlDbTypeName.BigInt },
{typeof(int),SqlDbTypeName.Int},
{ typeof(decimal),SqlDbTypeName.Decimal },
{ typeof(float),SqlDbTypeName.Float },
{ typeof(double),SqlDbTypeName.Double },
{ typeof(byte),SqlDbTypeName.Int },//类型待完
{ typeof(Guid),SqlDbTypeName.UniqueIdentifier}
};
public static string GetProperWithDbType(this PropertyInfo propertyInfo)
{
bool result = ProperWithDbType.TryGetValue(propertyInfo.PropertyType, out string value);
if (result)
{
return value;
}
return SqlDbTypeName.NVarChar;
}
/// <summary>
/// 验证数据库字段类型与值是否正确,
/// </summary>
/// <param name="dbType">数据库字段类型(如varchar,nvarchar,decimal,不要带后面长度如:varchar(50))</param>
/// <param name="value">值</param>
/// <param name="propertyInfo">要验证的类的属性,若不为null,则会判断字符串的长度是否正确</param>
/// <returns>(bool, string, object)bool成否校验成功,string校验失败信息,object,当前校验的值</returns>
public static (bool, string, object) ValidationVal(this string dbType, object value, PropertyInfo propertyInfo = null)
{
if (string.IsNullOrEmpty(dbType))
{
dbType = propertyInfo != null ? propertyInfo.GetProperWithDbType() : SqlDbTypeName.NVarChar;
}
dbType = dbType.ToLower();
string val = value?.ToString();
//验证长度
string reslutMsg = string.Empty;
if (dbType == SqlDbTypeName.Int || dbType == SqlDbTypeName.BigInt)
{
if (!value.IsInt())
reslutMsg = "只能为有效整数";
}
else if (dbType == SqlDbTypeName.DateTime
|| dbType == SqlDbTypeName.Date
|| dbType == SqlDbTypeName.SmallDateTime
|| dbType == SqlDbTypeName.SmallDate
)
{
if (!value.IsDate())
reslutMsg = "必须为日期格式";
}
else if (dbType == SqlDbTypeName.Float || dbType == SqlDbTypeName.Decimal || dbType == SqlDbTypeName.Double)
{
string formatString = string.Empty;
if (propertyInfo != null)
formatString = propertyInfo.GetTypeCustomValue<DisplayFormatAttribute>(x => x.DataFormatString);
//if (string.IsNullOrEmpty(formatString))
// throw new Exception("请对字段" + propertyInfo?.Name + "添加DisplayFormat属性标识");
if (!val.IsNumber(formatString))
{
string[] arr = (formatString ?? "10,0").Split(',');
reslutMsg = $"整数{arr[0]}最多位,小数最多{arr[1]}位";
}
}
else if (dbType == SqlDbTypeName.UniqueIdentifier)
{
if (!val.IsGuid())
{
reslutMsg = propertyInfo.Name + "Guid不正确";
}
}
else if (propertyInfo != null
&& (dbType == SqlDbTypeName.VarChar
|| dbType == SqlDbTypeName.NVarChar
|| dbType == SqlDbTypeName.NChar
|| dbType == SqlDbTypeName.Char
|| dbType == SqlDbTypeName.Text))
{
//默认nvarchar(max) 、text 长度不能超过20000
if (val.Length > 20000)
{
reslutMsg = $"字符长度最多【20000】";
}
else
{
int length = propertyInfo.GetTypeCustomValue<MaxLengthAttribute>(x => new { x.Length }).GetInt();
if (length == 0) { return (true, null, null); }
//判断双字节与单字段
else if (length < 8000 &&
((dbType.Substring(0, 1) != "n"
&& Encoding.UTF8.GetBytes(val.ToCharArray()).Length > length)
|| val.Length > length)
)
{
reslutMsg = $"最多只能【{length}】个字符。";
}
}
}
if (!string.IsNullOrEmpty(reslutMsg) && propertyInfo != null)
{
reslutMsg = propertyInfo.GetDisplayName() + reslutMsg;
}
return (reslutMsg == "" ? true : false, reslutMsg, value);
}
public static string GetDisplayName(this PropertyInfo property)
{
string displayName = property.GetTypeCustomValue<DisplayAttribute>(x => new { x.Name });
if (string.IsNullOrEmpty(displayName))
{
return property.Name;
}
return displayName;
}
/// <summary>
/// 获取属性的指定属性
/// </summary>
/// <param name="propertyInfo"></param>
/// <param name="type"></param>
/// <returns></returns>
public static object GetTypeCustomAttributes(this MemberInfo member, Type type)
{
object[] obj = member.GetCustomAttributes(type, false);
if (obj.Length == 0) return null;
return obj[0];
}
/// <summary>
/// 获取类的多个指定属性的值
/// </summary>
/// <param name="member">当前类</param>
/// <param name="type">指定的类</param>
/// <param name="expression">指定属性的值 格式 Expression<Func<entityt, object>> exp = x => new { x.字段1, x.字段2 };</param>
/// <returns>返回的是字段+value</returns>
public static Dictionary<string, string> GetTypeCustomValues<TEntity>(this MemberInfo member, Expression<Func<TEntity, object>> expression)
{
var attr = member.GetTypeCustomAttributes(typeof(TEntity));
if (attr == null)
{
return null;
}
string[] propertyName = expression.GetExpressionProperty();
Dictionary<string, string> propertyKeyValues = new Dictionary<string, string>();
foreach (PropertyInfo property in attr.GetType().GetProperties())
{
if (propertyName.Contains(property.Name))
{
propertyKeyValues[property.Name] = (property.GetValue(attr) ?? string.Empty).ToString();
}
}
return propertyKeyValues;
}
/// <summary>
/// 获取类的单个指定属性的值(只会返回第一个属性的值)
/// </summary>
/// <param name="member">当前类</param>
/// <param name="type">指定的类</param>
/// <param name="expression">指定属性的值 格式 Expression<Func<entityt, object>> exp = x => new { x.字段1, x.字段2 };</param>
/// <returns></returns>
public static string GetTypeCustomValue<TEntity>(this MemberInfo member, Expression<Func<TEntity, object>> expression)
{
var propertyKeyValues = member.GetTypeCustomValues(expression);
if (propertyKeyValues == null || propertyKeyValues.Count == 0)
{
return null;
}
return propertyKeyValues.First().Value ?? "";
}
/// <summary>
/// 获取表带有EntityAttribute属性的真实表名
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static string GetEntityTableName(this Type type)
{
Attribute attribute = type.GetCustomAttribute(typeof(EntityAttribute));
if (attribute != null && attribute is EntityAttribute)
{
return (attribute as EntityAttribute).TableName ?? type.Name;
}
return type.Name;
}
}
public class ArrayEntity
{
public string column1 { get; set; }
}
public enum FieldType
{
VarChar = 0,
NvarChar,
Int,
BigInt,
UniqueIdentifier
}
public enum EntityToSqlTempName
{
TempInsert = 0
}

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Tiobon.Core.Common.DB.Dapper.Extensions;
/// <summary>
/// 泛型扩展
/// </summary>
public static class GenericExtension
{
public static DataTable ToDataTable<T>(this IEnumerable<T> source, Expression<Func<T, object>> columns = null, bool contianKey = true)
{
DataTable dtReturn = new DataTable();
if (source == null) return dtReturn;
PropertyInfo[] oProps = typeof(T).GetProperties()
.Where(x => x.PropertyType.Name != "List`1").ToArray();
if (columns != null)
{
string[] columnArray = columns.GetExpressionToArray();
oProps = oProps.Where(x => columnArray.Contains(x.Name)).ToArray();
}
//移除自增主键
PropertyInfo keyType = oProps.GetKeyProperty();// oProps.GetKeyProperty()?.PropertyType;
if (!contianKey && keyType != null && (keyType.PropertyType == typeof(int) || keyType.PropertyType == typeof(long)))
{
oProps = oProps.Where(x => x.Name != keyType.Name).ToArray();
}
foreach (var pi in oProps)
{
var colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
foreach (var rec in source)
{
var dr = dtReturn.NewRow();
foreach (var pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null
? DBNull.Value
: pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
}

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Tiobon.Core.Common.DB.Dapper.Enums;
namespace Tiobon.Core.Common.DB.Dapper.Extensions
{
public static class LambdaExtensions
{
/// <summary>
/// 获取对象表达式指定属性的值
/// 如获取:Out_Scheduling对象的ID或基他字段
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="expression">格式 Expression<Func<Out_Scheduling, object>>sch=x=>new {x.v1,x.v2} or x=>x.v1 解析里面的值返回为数组</param>
/// <returns></returns>
public static string[] GetExpressionToArray<TEntity>(this Expression<Func<TEntity, object>> expression)
{
string[] propertyNames = null;
if (expression.Body is MemberExpression)
{
propertyNames = new string[] { ((MemberExpression)expression.Body).Member.Name };
}
else
{
propertyNames = expression.GetExpressionProperty().Distinct().ToArray();
}
return propertyNames;
}
/// <summary>
/// 属性判断待完
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static IEnumerable<PropertyInfo> GetGenericProperties(this Type type)
{
return type.GetProperties().GetGenericProperties();
}
/// <summary>
/// 属性判断待完
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public static IEnumerable<PropertyInfo> GetGenericProperties(this IEnumerable<PropertyInfo> properties)
{
return properties.Where(x => !x.PropertyType.IsGenericType && x.PropertyType.GetInterface("IList") == null || x.PropertyType.GetInterface("IEnumerable", false) == null);
}
}
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
}
}

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Tiobon.Core.Common.DB.Dapper.Extensions;
public static class MethodInfoExtensions
{
public static string GetFullName(this MethodInfo method)
{
if (method.DeclaringType == null)
{
return $@"{method.Name}";
}
return $"{method.DeclaringType.FullName}.{method.Name}";
}
}

@ -0,0 +1,31 @@
using Tiobon.Core.Common.DB.Dapper.BaseProvider.ServerMapPath;
using System;
using System.Collections.Generic;
using System.Text;
using Tiobon.Core.Common.DB.Dapper.Extensions.AutofacManager;
namespace Tiobon.Core.Common.DB.Dapper.Extensions
{
public static class ServerExtension
{
/// <summary>
/// 返回的路径后面不带/,拼接时需要自己加上/
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string MapPath(this string path)
{
return MapPath(path, false);
}
/// <summary>
///
/// </summary>
/// <param name="path"></param>
/// <param name="rootPath">获取wwwroot路径</param>
/// <returns></returns>
public static string MapPath(this string path,bool rootPath)
{
return AutofacContainerModule.GetService<IPathProvider>().MapPath(path,rootPath);
}
}
}

@ -0,0 +1,18 @@
using Tiobon.Core.Common.DB.Dapper.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
namespace Tiobon.Core.Common.DB.Dapper.Extensions
{
public static class ServiceProviderManagerExtension
{
public static object GetService(this Type serviceType)
{
// HttpContext.Current.RequestServices.GetRequiredService<T>(serviceType);
return Utilities.HttpContext.Current.RequestServices.GetService(serviceType);
}
}
}

@ -0,0 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
namespace Tiobon.Core.Common.DB.Dapper.Extensions;
/// <summary>
/// Tiobon.Core.Common.DB.Dapper 启动服务
/// </summary>
public static class SimpleDapperSetup
{
public static void AddSimpleDapperSetup(this IServiceCollection services)
{
AppSetting.Init();
}
}

@ -0,0 +1,117 @@
using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Tiobon.Core.Common.DB.Dapper.Const;
using Tiobon.Core.Common.DB.Dapper.Enums;
namespace Tiobon.Core.Common.DB.Dapper.Extensions
{
public static class StringExtension
{
public static bool _windows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static string ReplacePath(this string path)
{
if (string.IsNullOrEmpty(path))
return "";
if (_windows)
return path.Replace("/", "\\");
return path.Replace("\\", "/");
}
public static bool GetGuid(this string guid, out Guid outId)
{
Guid emptyId = Guid.Empty;
return Guid.TryParse(guid, out outId);
}
public static bool IsGuid(this string guid)
{
Guid newId;
return guid.GetGuid(out newId);
}
public static bool IsInt(this object obj)
{
if (obj == null)
return false;
bool reslut = Int32.TryParse(obj.ToString(), out int _number);
return reslut;
}
public static bool IsDate(this object str)
{
return str.IsDate(out _);
}
public static bool IsDate(this object str, out DateTime dateTime)
{
dateTime = DateTime.Now;
if (str == null || str.ToString() == "")
{
return false;
}
return DateTime.TryParse(str.ToString(), out dateTime);
}
/// <summary>
/// 根据传入格式判断是否为小数
/// </summary>
/// <param name="str"></param>
/// <param name="formatString">18,5</param>
/// <returns></returns>
public static bool IsNumber(this string str, string formatString)
{
if (string.IsNullOrEmpty(str))
return false;
int precision = 32;
int scale = 5;
try
{
if (string.IsNullOrEmpty(formatString))
{
precision = 10;
scale = 2;
}
else
{
string[] numbers = formatString.Split(',');
precision = Convert.ToInt32(numbers[0]);
scale = numbers.Length == 0 ? 2 : Convert.ToInt32(numbers[1]);
}
}
catch { };
return IsNumber(str, precision, scale);
}
/**/
/// <summary>
/// 判断一个字符串是否为合法数字(指定整数位数和小数位数)
/// </summary>
/// <param name="str">字符串</param>
/// <param name="precision">整数位数</param>
/// <param name="scale">小数位数</param>
/// <returns></returns>
public static bool IsNumber(this string str, int precision, int scale)
{
if ((precision == 0) && (scale == 0))
{
return false;
}
string pattern = @"(^\d{1," + precision + "}";
if (scale > 0)
{
pattern += @"\.\d{0," + scale + "}$)|" + pattern;
}
pattern += "$)";
return Regex.IsMatch(str, pattern);
}
public static int GetInt(this object obj)
{
if (obj == null)
return 0;
int.TryParse(obj.ToString(), out int _number);
return _number;
}
}
}

@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Dapper;
namespace Tiobon.Core.Common.DB.Dapper;
public interface ISqlDapper
{
/// <summary>
/// var p = new object();
// p.Add("@a", 11);
//p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
//p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
// /// </summary>
IDbConnection Connection { get; }
/// <typeparam name="T"></typeparam>
/// <param name="sql"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <returns></returns>
List<T> QueryList<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false) where T : class;
Task<List<T>> QueryListAsync<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false, int? commandTimeout = null) where T : class;
T QueryFirst<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false) where T : class;
Task<T> QueryFirstAsync<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false, int? commandTimeout = null) where T : class;
object ExecuteScalar(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false);
Task<object> ExecuteScalarAsync(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false);
int ExcuteNonQuery(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false);
IDataReader ExecuteReader(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false);
SqlMapper.GridReader QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false);
(List<T1>, List<T2>) QueryMultiple<T1, T2>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false);
(List<T1>, List<T2>, List<T3>) QueryMultiple<T1, T2, T3>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false);
DataTable GetDataTable(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false);
Task<DataTable> GetDataTableAsync(string cmd, object param = null, IDbTransaction transaction = null, CommandType? commandType = null, int? commandTimeout = null);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int Add<T>(T entity, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = false);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int AddRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = false);
/// <summary>
/// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">实体必须带主键</param>
/// <param name="updateFileds">指定更新的字段x=new {x.a,x.b}</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int Update<T>(T entity, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = false);
/// <summary>
/// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">实体必须带主键</param>
/// <param name="updateFileds">指定更新的字段x=new {x.a,x.b}</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int UpdateRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = false);
int DelWithKey<T>(object[] keys);
int DelWithKey<T>(object[] keys, bool beginTransaction = false);
/// <summary>
/// sqlserver批量写入
/// 使用时DataTable table表字段顺序要和数据库字段顺序一致
/// <summary>
/// mysql批量写入
/// </summary>
/// <param name="table"></param>
/// <param name="tableName"></param>
/// <param name="tmpPath">默认当前下载路径</param>
/// <param name="fileName">默认$"{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv"</param>
/// <returns></returns>
int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="tableName"></param>
/// <param name="columns">所包含的列</param>
/// <param name="sqlBulkCopyOptions"></param>
/// <param name="fileName"></param>
/// <param name="tmpPath"></param>
/// <returns></returns>
int BulkInsert<T>(List<T> entities, string tableName = null,
Expression<Func<T, object>> columns = null,
SqlBulkCopyOptions? sqlBulkCopyOptions = null);
T Execute<T>(Func<IDbConnection, IDbTransaction, T> func, bool beginTransaction = false, bool disposeConn = true);
int ExecuteDML(string cmd, object param = null, CommandType? commandType = null, IDbTransaction dbTransaction = null);
Task<int> ExecuteDMLAsync(string cmd, object param = null, CommandType? commandType = null, IDbTransaction dbTransaction = null);
IDbTransaction GetNewTransaction();
void CommitTransaction(IDbTransaction dbTransaction);
void RollbackTransaction(IDbTransaction dbTransaction);
DataTable GetTransDataTable(string cmd, object param = null, CommandType? commandType = null, IDbTransaction dbTransaction = null);
T QueryTransFirst<T>(string cmd, object param = null, CommandType? commandType = null, IDbTransaction dbTransaction = null) where T : class;
}

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq.Expressions;
using Dapper;
namespace Tiobon.Core.Common.DB.Dapper;
public interface ITransDapper
{
void BeginTransaction(Func<ITransDapper, bool> action, Action<Exception> error, bool disposeConn = true);
/// <summary>
/// var p = new object();
// p.Add("@a", 11);
//p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
//p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
// /// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sql"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <returns></returns>
List<T> QueryList<T>(string cmd, object param, CommandType? commandType = null) where T : class;
T QueryFirst<T>(string cmd, object param, CommandType? commandType = null) where T : class;
object ExecuteScalar(string cmd, object param, CommandType? commandType = null);
int ExcuteNonQuery(string cmd, object param, CommandType? commandType = null);
IDataReader ExecuteReader(string cmd, object param, CommandType? commandType = null);
SqlMapper.GridReader QueryMultiple(string cmd, object param, CommandType? commandType = null);
(List<T1>, List<T2>) QueryMultiple<T1, T2>(string cmd, object param, CommandType? commandType = null);
(List<T1>, List<T2>, List<T3>) QueryMultiple<T1, T2, T3>(string cmd, object param, CommandType? commandType = null);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int Add<T>(T entity, Expression<Func<T, object>> updateFileds = null);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int AddRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null);
/// <summary>
/// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">实体必须带主键</param>
/// <param name="updateFileds">指定更新的字段x=new {x.a,x.b}</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int Update<T>(T entity, Expression<Func<T, object>> updateFileds = null);
/// <summary>
/// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">实体必须带主键</param>
/// <param name="updateFileds">指定更新的字段x=new {x.a,x.b}</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
int UpdateRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null);
int DelWithKey<T>(params object[] keys);
/// <summary>
/// sqlserver批量写入
/// 使用时DataTable table表字段顺序要和数据库字段顺序一致
/// <summary>
/// mysql批量写入
/// </summary>
/// <param name="table"></param>
/// <param name="tableName"></param>
/// <param name="tmpPath">默认当前下载路径</param>
/// <param name="fileName">默认$"{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv"</param>
/// <returns></returns>
int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="tableName"></param>
/// <param name="columns">所包含的列</param>
/// <param name="sqlBulkCopyOptions"></param>
/// <param name="fileName"></param>
/// <param name="tmpPath"></param>
/// <returns></returns>
int BulkInsert<T>(List<T> entities, string tableName = null,
Expression<Func<T, object>> columns = null,
SqlBulkCopyOptions? sqlBulkCopyOptions = null);
DataTable GetDataTable(string cmd, object param, CommandType? commandType = null);
}

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile></DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Content Remove="C:\Users\Administrator.CH-202209031648\.nuget\packages\dotnetcore.npoi\1.2.3\contentFiles\any\netstandard2.0\NOTICE.TXT" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="MySql.Data" Version="8.0.26" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.83" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
</ItemGroup>
</Project>

@ -0,0 +1,665 @@

using Dapper;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Tiobon.Core.Common.DB.Dapper.Const;
using Tiobon.Core.Common.DB.Dapper.DBManager;
using Tiobon.Core.Common.DB.Dapper.Enums;
using Tiobon.Core.Common.DB.Dapper.Extensions;
using Tiobon.Core.Common.DB.Dapper.Utilities;
using System.Threading.Tasks;
namespace Tiobon.Core.Common.DB.Dapper;
public class SqlDapper : ISqlDapper
{
private string _connectionString;
private IDbConnection _connection { get; set; }
public IDbConnection Connection
{
get
{
if (_connection == null || _connection.State == ConnectionState.Closed)
{
_connection = DBServerProvider.GetDbConnection(_connectionString);
}
return _connection;
}
}
public SqlDapper()
{
_connectionString = DBServerProvider.GetConnectionString();
}
/// <summary>
/// string mySql = "Data Source=132.232.2.109;Database=mysql;User
/// ID=root;Password=mysql;pooling=true;CharSet=utf8;port=3306;sslmode=none";
/// this.conn = new MySql.Data.MySqlClient.MySqlConnection(mySql);
/// </summary>
/// <param name="connKeyName"></param>
public SqlDapper(string connKeyName)
{
_connectionString = DBServerProvider.GetConnectionString(connKeyName);
}
/// <summary>
/// var p = new object();
// p.Add("@a", 11);
//p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
//p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
// /// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cmd"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <returns></returns>
public List<T> QueryList<T>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) where T : class
{
return Execute((conn, dbTransaction) =>
{
return conn.Query<T>(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text).ToList();
}, beginTransaction);
}
public async Task<List<T>> QueryListAsync<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false, int? commandTimeout = null) where T : class
{
return await Execute(async (conn, dbTransaction) =>
{
return (await conn.QueryAsync<T>(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text)).ToList();
}, beginTransaction);
}
public T QueryFirst<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false) where T : class
{
List<T> list = QueryList<T>(cmd, param, commandType: commandType ?? CommandType.Text, beginTransaction: beginTransaction).ToList();
return list.Count == 0 ? null : list[0];
}
public async Task<T> QueryFirstAsync<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false, int? commandTimeout = null) where T : class
{
var data = await QueryListAsync<T>(cmd, param, commandType, beginTransaction, commandTimeout);
List<T> list = data.ToList();
return !list.Any() ? null : list[0];
}
public object ExecuteScalar(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
try
{
return Execute((conn, dbTransaction) =>
{
return conn.ExecuteScalar(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, beginTransaction);
}
catch (Exception)
{
throw;
}
}
public async Task<object> ExecuteScalarAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
try
{
return await Execute(async (conn, dbTransaction) =>
{
return await conn.ExecuteScalarAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, beginTransaction);
}
catch (Exception)
{
throw;
}
}
public int ExcuteNonQuery(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
return Execute((conn, dbTransaction) =>
{
return conn.Execute(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, beginTransaction);
}
public IDataReader ExecuteReader(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
return Execute((conn, dbTransaction) =>
{
return conn.ExecuteReader(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, beginTransaction, false);
}
public SqlMapper.GridReader QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
return Execute((conn, dbTransaction) =>
{
return conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, beginTransaction, false);
}
/// <summary>
/// 获取output值 param.Get<int>("@b");
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <param name="cmd"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <param name="dbTransaction"></param>
/// <returns></returns>
public (List<T1>, List<T2>) QueryMultiple<T1, T2>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
using (SqlMapper.GridReader reader = QueryMultiple(cmd, param, commandType, beginTransaction))
{
return (reader.Read<T1>().ToList(), reader.Read<T2>().ToList());
}
}
public (List<T1>, List<T2>, List<T3>) QueryMultiple<T1, T2, T3>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
using (SqlMapper.GridReader reader = QueryMultiple(cmd, param, commandType, beginTransaction))
{
return (reader.Read<T1>().ToList(), reader.Read<T2>().ToList(), reader.Read<T3>().ToList());
}
}
public T Execute<T>(Func<IDbConnection, IDbTransaction, T> func, bool beginTransaction = false, bool disposeConn = true)
{
IDbTransaction dbTransaction = null;
if (beginTransaction)
{
Connection.Open();
dbTransaction = Connection.BeginTransaction();
}
try
{
T reslutT = func(Connection, dbTransaction);
dbTransaction?.Commit();
return reslutT;
}
catch (Exception)
{
dbTransaction?.Rollback();
Connection.Dispose();
throw;
}
finally
{
if (disposeConn)
{
Connection.Dispose();
}
}
}
public async Task<T> ExecuteAsync<T>(Func<IDbConnection, IDbTransaction, Task<T>> funcAsync, bool beginTransaction = false, bool disposeConn = true)
{
IDbTransaction dbTransaction = null;
if (beginTransaction)
{
Connection.Open();
dbTransaction = Connection.BeginTransaction();
}
try
{
T reslutT = await funcAsync(Connection, dbTransaction);
dbTransaction?.Commit();
return reslutT;
}
catch (Exception)
{
dbTransaction?.Rollback();
Connection.Dispose();
throw;
}
finally
{
if (disposeConn)
{
Connection.Dispose();
}
}
}
public int ExecuteDML(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null)
{
return ExecuteDML((conn, dbTransaction) =>
{
return conn.Execute(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, dbTransaction, false);
}
public async Task<int> ExecuteDMLAsync(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null)
{
return await ExecuteDML(async (conn, dbTransaction) =>
{
return await conn.ExecuteAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, dbTransaction, false);
}
public IDataReader ExecuteDMLReader(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null)
{
return ExecuteDML((conn, dbTransaction) =>
{
return conn.ExecuteReader(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
}, dbTransaction, false);
}
/// <summary>
/// 执行数据库
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func"></param>
/// <param name="dbTransaction"></param>
/// <param name="disposeConn"></param>
/// <returns></returns>
public T ExecuteDML<T>(Func<IDbConnection, IDbTransaction, T> func, IDbTransaction dbTransaction = null, bool disposeConn = false)
{
if (dbTransaction == null)
{
try
{
T reslutT = func(Connection, dbTransaction);
dbTransaction?.Commit();
return reslutT;
}
catch (Exception)
{
dbTransaction?.Rollback();
Connection.Dispose();
throw;
}
finally
{
if (disposeConn)
Connection.Dispose();
}
}
else
{
//Connection.Open();
try
{
if (_connection == null)
_connection = dbTransaction.Connection;
T reslutT = func(Connection, dbTransaction);
return reslutT;
}
catch (Exception)
{
Connection.Dispose();
throw;
}
finally
{
if (disposeConn)
Connection.Dispose();
}
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public int Add<T>(T entity, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = false)
{
return AddRange(new T[] { entity }, updateFileds, beginTransaction);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public int AddRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> addFileds = null, bool beginTransaction = true)
{
Type entityType = typeof(T);
var key = entityType.GetKeyProperty();
if (key == null)
{
throw new Exception("实体必须包括主键才能批量更新");
}
string[] columns;
//指定插入的字段
if (addFileds != null)
{
columns = addFileds.GetExpressionToArray();
}
else
{
var properties = entityType.GetGenericProperties();
if (key.PropertyType != typeof(Guid))
{
properties = properties.Where(x => x.Name != key.Name).ToArray();
}
columns = properties.Select(x => x.Name).ToArray();
}
string sql = null;
bool mysql = DBType.Name == DbCurrentType.MySql.ToString();
if (mysql)
{
//mysql批量写入待优化
sql = $"insert into {entityType.GetEntityTableName()}({string.Join(",", columns)})" +
$"values(@{string.Join(",@", columns)});";
}
else
{
//sqlserver通过临时表批量写入
sql = $"insert into {entityType.GetEntityTableName()}({string.Join(",", columns)})" +
$"select * from {EntityToSqlTempName.TempInsert};";
sql = entities.GetEntitySql(entityType == typeof(Guid), sql, null, addFileds, null);
}
return Execute((conn, dbTransaction) =>
{
return conn.Execute(sql, mysql ? entities.ToList() : null);
}, beginTransaction);
}
/// <summary>
/// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">实体必须带主键</param>
/// <param name="updateFileds">指定更新的字段x=new {x.a,x.b}</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public int Update<T>(T entity, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = true)
{
return UpdateRange(new T[] { entity }, updateFileds, beginTransaction);
}
/// <summary>
///(根据主键批量更新实体) sqlserver使用的临时表参数化批量更新,mysql待优化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">实体必须带主键</param>
/// <param name="updateFileds">批定更新字段</param>
/// <param name="beginTransaction"></param>
/// <returns></returns>
public int UpdateRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = true)
{
Type entityType = typeof(T);
var key = entityType.GetKeyProperty();
if (key == null)
{
throw new Exception("实体必须包括主键才能批量更新");
}
var properties = entityType.GetGenericProperties()
.Where(x => x.Name != key.Name);
if (updateFileds != null)
{
properties = properties.Where(x => updateFileds.GetExpressionToArray().Contains(x.Name));
}
if (DBType.Name == DbCurrentType.MySql.ToString())
{
List<string> paramsList = new List<string>();
foreach (var item in properties)
{
paramsList.Add(item.Name + "=@" + item.Name);
}
string sqltext = $@"UPDATE {entityType.GetEntityTableName()} SET {string.Join(",", paramsList)} WHERE {entityType.GetKeyName()} = @{entityType.GetKeyName()} ;";
return ExcuteNonQuery(sqltext, entities, CommandType.Text, true);
// throw new Exception("mysql批量更新未实现");
}
string fileds = string.Join(",", properties.Select(x => $" a.{x.Name}=b.{x.Name}").ToArray());
string sql = $"update a set {fileds} from {entityType.GetEntityTableName()} as a inner join {EntityToSqlTempName.TempInsert.ToString()} as b on a.{key.Name}=b.{key.Name}";
sql = entities.ToList().GetEntitySql(true, sql, null, updateFileds, null);
return ExcuteNonQuery(sql, null, CommandType.Text, true);
}
public int DelWithKey<T>(object[] keys, bool beginTransaction = false)
{
Type entityType = typeof(T);
var keyProperty = entityType.GetKeyProperty();
if (keyProperty == null || keys == null || keys.Length == 0) return 0;
IEnumerable<(bool, string, object)> validation = keyProperty.ValidationValueForDbType(keys);
if (validation.Any(x => !x.Item1))
{
throw new Exception($"主键类型【{validation.Where(x => !x.Item1).Select(s => s.Item3).FirstOrDefault()}】不正确");
}
string tKey = entityType.GetKeyProperty().Name;
FieldType fieldType = entityType.GetFieldType();
string joinKeys = fieldType == FieldType.Int || fieldType == FieldType.BigInt
? string.Join(",", keys)
: $"'{string.Join("','", keys)}'";
string sql = $"DELETE FROM {entityType.GetEntityTableName()} where {tKey} in ({joinKeys});";
return (int)ExecuteScalar(sql, null);
}
/// <summary>
/// 使用key批量删除
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="keys"></param>
/// <returns></returns>
public int DelWithKey<T>(object[] keys)
{
return DelWithKey<T>(keys, false);
}
#region 批量插入
/// <summary>
/// 通过Bulk批量插入
/// </summary>
/// <param name="table"></param>
/// <param name="tableName"></param>
/// <param name="sqlBulkCopyOptions"></param>
/// <param name="dbKeyName"></param>
/// <returns></returns>
private int MSSqlBulkInsert(DataTable table, string tableName, SqlBulkCopyOptions sqlBulkCopyOptions = SqlBulkCopyOptions.UseInternalTransaction, string dbKeyName = null)
{
if (!string.IsNullOrEmpty(dbKeyName))
{
Connection.ConnectionString = DBServerProvider.GetConnectionString(dbKeyName);
}
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(Connection.ConnectionString, sqlBulkCopyOptions))
{
sqlBulkCopy.DestinationTableName = tableName;
sqlBulkCopy.BatchSize = table.Rows.Count;
for (int i = 0; i < table.Columns.Count; i++)
{
sqlBulkCopy.ColumnMappings.Add(table.Columns[i].ColumnName, table.Columns[i].ColumnName);
}
sqlBulkCopy.WriteToServer(table);
return table.Rows.Count;
}
}
public int BulkInsert<T>(List<T> entities, string tableName = null,
Expression<Func<T, object>> columns = null,
SqlBulkCopyOptions? sqlBulkCopyOptions = null)
{
DataTable table = entities.ToDataTable(columns, false);
return BulkInsert(table, tableName ?? typeof(T).GetEntityTableName(), sqlBulkCopyOptions);
}
public int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null)
{
if (!string.IsNullOrEmpty(tmpPath))
{
tmpPath = tmpPath.ReplacePath();
}
if (Connection.GetType().Name == "MySqlConnection")
return MySqlBulkInsert(table, tableName, fileName, tmpPath);
return MSSqlBulkInsert(table, tableName, sqlBulkCopyOptions ?? SqlBulkCopyOptions.KeepIdentity);
}
#endregion
#region 大批量数据插入,返回成功插入行数
/// <summary>
///大批量数据插入,返回成功插入行数
/// </summary>
/// <param name="connectionString">数据库连接字符串</param>
/// <param name="table">数据表</param>
/// <returns>返回成功插入行数</returns>
private int MySqlBulkInsert(DataTable table, string tableName, string fileName = null, string tmpPath = null)
{
if (table.Rows.Count == 0)
return 0;
tmpPath = tmpPath ?? FileHelper.GetCurrentDownLoadPath();
fileName = fileName ?? $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv";
int insertCount = 0;
string csv = DataTableToCsv(table);
FileHelper.WriteFile(tmpPath, fileName, csv);
string path = tmpPath + fileName;
try
{
if (Connection.State == ConnectionState.Closed)
Connection.Open();
using (IDbTransaction tran = Connection.BeginTransaction())
{
MySqlBulkLoader bulk = new MySqlBulkLoader(Connection as MySqlConnection)
{
FieldTerminator = ",",
FieldQuotationCharacter = '"',
EscapeCharacter = '"',
LineTerminator = "\r\n",
FileName = path.ReplacePath(),
NumberOfLinesToSkip = 0,
TableName = tableName,
};
bulk.Columns.AddRange(table.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).ToList());
insertCount = bulk.Load();
tran.Commit();
}
}
catch (Exception) { throw; }
finally
{
Connection?.Dispose();
Connection?.Close();
}
return insertCount;
// File.Delete(path);
}
#endregion
#region 将DataTable转换为标准的CSV
/// <summary>
///将DataTable转换为标准的CSV
/// </summary>
/// <param name="table">数据表</param>
/// <returns>返回标准的CSV</returns>
private string DataTableToCsv(DataTable table)
{
//以半角逗号(即,)作分隔符,列为空也要表达其存在。
//列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。
//列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
StringBuilder sb = new StringBuilder();
DataColumn colum;
Type typeString = typeof(string);
Type typeDate = typeof(DateTime);
foreach (DataRow row in table.Rows)
{
for (int i = 0; i < table.Columns.Count; i++)
{
colum = table.Columns[i];
if (i != 0) sb.Append(",");
if (colum.DataType == typeString && row[colum].ToString().Contains(","))
{
sb.Append("\"" + row[colum].ToString().Replace("\"", "\"\"") + "\"");
}
else if (colum.DataType == typeDate)
{
//centos系统里把datatable里的日期转换成了10/18/18 3:26:15 PM格式
bool b = DateTime.TryParse(row[colum].ToString(), out DateTime dt);
sb.Append(b ? dt.ToString("yyyy-MM-dd HH:mm:ss") : "");
}
else sb.Append(row[colum].ToString());
}
sb.AppendLine();
}
return sb.ToString();
}
#endregion
#region 返回DataTable
/// <summary>
/// 返回DataTable
/// </summary>
/// <param name="cmd"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <param name="beginTransaction"></param>
/// <returns></returns>
public DataTable GetDataTable(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false)
{
DataTable table = new DataTable("MyTable");
var reader = ExecuteReader(cmd, param, commandType, beginTransaction);
table.Load(reader);
return table;
}
public DataTable GetTransDataTable(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null)
{
DataTable table = new DataTable("MyTable");
var reader = ExecuteDMLReader(cmd, param, commandType, dbTransaction);
table.Load(reader);
return table;
}
public async Task<DataTable> GetDataTableAsync(string cmd, object param = null, IDbTransaction transaction = null, CommandType? commandType = null, int? commandTimeout = null)
{
DataTable table = new DataTable("MyTable");
var reader = await Connection.ExecuteReaderAsync(cmd, param, transaction, commandTimeout, commandType: commandType ?? CommandType.Text); ;
table.Load(reader);
return table;
}
#endregion
#region Transaction
public IDbTransaction GetNewTransaction()
{
Connection.Open();
IDbTransaction trans = Connection.BeginTransaction();
return trans;
}
public void CommitTransaction(IDbTransaction dbTransaction)
{
dbTransaction?.Commit();
}
public void RollbackTransaction(IDbTransaction dbTransaction)
{
dbTransaction?.Rollback();
}
#endregion Transaction
#region 查询按实体返回
public List<T> QueryTransList<T>(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null) where T : class
{
return ExecuteDML((conn, dbTransaction) =>
{
return conn.Query<T>(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text).ToList();
}, dbTransaction, false);
}
public T QueryTransFirst<T>(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null) where T : class
{
List<T> list = QueryTransList<T>(cmd, param, commandType: commandType ?? CommandType.Text, dbTransaction: dbTransaction).ToList();
return list.Count == 0 ? null : list[0];
}
#endregion
}

@ -0,0 +1,495 @@

using Dapper;
using Tiobon.Core.Common.DB.Dapper.Const;
using Tiobon.Core.Common.DB.Dapper.DBManager;
using Tiobon.Core.Common.DB.Dapper.Enums;
using Tiobon.Core.Common.DB.Dapper.Extensions;
using Tiobon.Core.Common.DB.Dapper.Utilities;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.SqlClient;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace Tiobon.Core.Common.DB.Dapper;
public class TransDapper : ITransDapper
{
private string _connectionString;
private IDbConnection _connection { get; set; }
public IDbConnection Connection
{
get
{
if (_connection == null || _connection.State == ConnectionState.Closed)
_connection = DBServerProvider.GetDbConnection(_connectionString);
return _connection;
}
}
public TransDapper()
{
_connectionString = DBServerProvider.GetConnectionString();
}
/// <summary>
/// string mySql = "Data Source=132.232.2.109;Database=mysql;User
/// ID=root;Password=mysql;pooling=true;CharSet=utf8;port=3306;sslmode=none";
/// this.conn = new MySql.Data.MySqlClient.MySqlConnection(mySql);
/// </summary>
/// <param name="connKeyName"></param>
public TransDapper(string connKeyName)
{
_connectionString = DBServerProvider.GetConnectionString(connKeyName);
}
private bool _transaction { get; set; }
/// <summary>
/// 增加Dapper事务处理
/// <param name="action"></param>
/// <param name="error"></param>
public void BeginTransaction(Func<ITransDapper, bool> action, Action<Exception> error, bool disposeConn = true)
{
_transaction = true;
try
{
Connection.Open();
dbTransaction = Connection.BeginTransaction();
bool result = action(this);
if (result)
{
dbTransaction?.Commit();
}
else
{
dbTransaction?.Rollback();
}
}
catch (Exception ex)
{
dbTransaction?.Rollback();
error(ex);
}
finally
{
if (!_transaction)
{
if (disposeConn)
{
Connection.Dispose();
}
dbTransaction?.Dispose();
}
dbTransaction?.Dispose();
_transaction = false;
}
}
/// <summary>
/// var p = new object();
// p.Add("@a", 11);
//p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
//p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
// /// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cmd"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <returns></returns>
public List<T> QueryList<T>(string cmd, object param, CommandType? commandType = null) where T : class
{
return Execute((conn) =>
{
return conn.Query<T>(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text).ToList();
});
}
public T QueryFirst<T>(string cmd, object param, CommandType? commandType = null) where T : class
{
List<T> list = QueryList<T>(cmd, param, commandType: commandType ?? CommandType.Text).ToList();
return list.Count == 0 ? null : list[0];
}
public object ExecuteScalar(string cmd, object param, CommandType? commandType = null)
{
return Execute((conn) =>
{
return conn.ExecuteScalar(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
});
}
public int ExcuteNonQuery(string cmd, object param, CommandType? commandType = null)
{
return Execute((conn) =>
{
return conn.Execute(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
});
}
public IDataReader ExecuteReader(string cmd, object param, CommandType? commandType = null)
{
return Execute((conn) =>
{
return conn.ExecuteReader(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
});
}
public SqlMapper.GridReader QueryMultiple(string cmd, object param, CommandType? commandType = null)
{
return Execute((conn) =>
{
return conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text);
});
}
/// <summary>
/// 获取output值 param.Get<int>("@b");
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <param name="cmd"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <param name="dbTransaction"></param>
/// <returns></returns>
public (List<T1>, List<T2>) QueryMultiple<T1, T2>(string cmd, object param, CommandType? commandType = null)
{
using (SqlMapper.GridReader reader = QueryMultiple(cmd, param, commandType))
{
return (reader.Read<T1>().ToList(), reader.Read<T2>().ToList());
}
}
public (List<T1>, List<T2>, List<T3>) QueryMultiple<T1, T2, T3>(string cmd, object param, CommandType? commandType = null)
{
using (SqlMapper.GridReader reader = QueryMultiple(cmd, param, commandType))
{
return (reader.Read<T1>().ToList(), reader.Read<T2>().ToList(), reader.Read<T3>().ToList());
}
}
IDbTransaction dbTransaction = null;
private T Execute<T>(Func<IDbConnection, T> func)
{
if (dbTransaction == null) throw new Exception("该方法用于事务,请使用DBHelper.Instance");
try
{
T reslutT = func(Connection);
return reslutT;
}
catch (Exception ex)
{
throw;
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public int Add<T>(T entity, Expression<Func<T, object>> updateFileds = null)
{
return AddRange(new T[] { entity }, updateFileds);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public int AddRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> addFileds = null)
{
Type entityType = typeof(T);
var key = entityType.GetKeyProperty();
if (key == null)
throw new Exception("实体必须包括主键才能批量更新!");
string[] columns;
//指定插入的字段
if (addFileds != null)
columns = addFileds.GetExpressionToArray();
else
{
var properties = entityType.GetGenericProperties().Where(x => !x.ContainsCustomAttributes(typeof(NotMappedAttribute)));
//&& !string.IsNullOrEmpty(entityType.GetProperty(x.Name).GetValue(entities.FirstOrDefault())?.ToString()));
//var value = entityType.GetProperty(property.Name).GetValue(mainEntity)?.ToString();
//if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
//{
// dbInsert.AddValue(key, value);
//}
//if (key.PropertyType != typeof(Guid))
//{
// properties = properties.Where(x => x.Name != key.Name).ToArray();
//}
// 排除插入的为空的字段,避免影响数据库中的默认值
//columns = properties.Select(x => x.Name).ToArray();
columns = properties.Where(x =>
{
foreach (var entitie in entities)
{
var data = typeof(T).GetProperty(x.Name).GetValue(entitie);
if (data != null)
return true;
}
return false;
}).Select(x => x.Name).ToArray();
}
string sql = null;
if (DBType.Name == DbCurrentType.MySql.ToString())
{
//mysql批量写入待优化
sql = $"insert into {entityType.GetEntityTableName()}({string.Join(",", columns)})" +
$"values(@{string.Join(",@", columns)});";
}
else if (DBType.Name == DbCurrentType.PgSql.ToString())
{
//todo pgsql批量写入 待检查是否正确
sql = $"insert into {entityType.GetEntityTableName()}({"\"" + string.Join("\",\"", columns) + "\""})" +
$"values(@{string.Join(",@", columns)});";
}
else
{
//sqlserver通过临时表批量写入
sql = $"insert into {entityType.GetEntityTableName()}({string.Join(",", columns)})" +
$"select {string.Join(",", columns)} from {EntityToSqlTempName.TempInsert};";
//sql = entities.GetEntitySql(entityType == typeof(Guid), sql, null, addFileds, null);
sql = entities.GetEntitySql(true, sql, null, addFileds, null);
}
return Execute((conn) =>
{
//todo pgsql待实现
return conn.Execute(sql, DBType.Name == DbCurrentType.MySql.ToString() || DBType.Name == DbCurrentType.PgSql.ToString() ? entities.ToList() : null, dbTransaction);
});
}
/// <summary>
/// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">实体必须带主键</param>
/// <param name="updateFileds">指定更新的字段x=new {x.a,x.b}</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public int Update<T>(T entity, Expression<Func<T, object>> updateFileds = null)
{
return UpdateRange(new T[] { entity }, updateFileds);
}
/// <summary>
///(根据主键批量更新实体) sqlserver使用的临时表参数化批量更新,mysql待优化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">实体必须带主键</param>
/// <param name="updateFileds">批定更新字段</param>
/// <param name="beginTransaction"></param>
/// <returns></returns>
public int UpdateRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null)
{
Type entityType = typeof(T);
var key = entityType.GetKeyProperty();
if (key == null)
throw new Exception("实体必须包括主键才能批量更新");
var properties = entityType.GetGenericProperties().Where(x => x.Name != key.Name && !x.ContainsCustomAttributes(typeof(NotMappedAttribute)));
if (updateFileds != null)
properties = properties.Where(x => updateFileds.GetExpressionToArray().Contains(x.Name));
if (DBType.Name == DbCurrentType.MySql.ToString())
{
List<string> paramsList = new List<string>();
foreach (var item in properties)
{
paramsList.Add(item.Name + "=@" + item.Name);
}
string sqltext = $@"UPDATE {entityType.GetEntityTableName()} SET {string.Join(",", paramsList)} WHERE {entityType.GetKeyName()} = @{entityType.GetKeyName()} ;";
return ExcuteNonQuery(sqltext, entities, CommandType.Text);
// throw new Exception("mysql批量更新未实现");
}
string fileds = string.Join(",", properties.Select(x => $" a.{x.Name}=b.{x.Name}").ToArray());
string sql = $"update a set {fileds} from {entityType.GetEntityTableName()} as a inner join {EntityToSqlTempName.TempInsert.ToString()} as b on a.{key.Name}=b.{key.Name}";
sql = entities.ToList().GetEntitySql(true, sql, null, updateFileds, null);
return ExcuteNonQuery(sql, null, CommandType.Text);
}
public int DelWithKey<T>(params object[] keys)
{
Type entityType = typeof(T);
var keyProperty = entityType.GetKeyProperty();
if (keyProperty == null || keys == null || keys.Length == 0) return 0;
IEnumerable<(bool, string, object)> validation = keyProperty.ValidationValueForDbType(keys);
if (validation.Any(x => !x.Item1))
throw new Exception($"主键类型【{validation.Where(x => !x.Item1).Select(s => s.Item3).FirstOrDefault()}】不正确");
string tKey = entityType.GetKeyProperty().Name;
FieldType fieldType = entityType.GetFieldType();
string joinKeys = fieldType == FieldType.Int || fieldType == FieldType.BigInt
? string.Join(",", keys)
: $"'{string.Join("','", keys)}'";
string sql = $"DELETE FROM {entityType.GetEntityTableName()} where {tKey} in ({joinKeys});";
return ExcuteNonQuery(sql, null);
}
/// <summary>
/// 通过Bulk批量插入
/// </summary>
/// <param name="table"></param>
/// <param name="tableName"></param>
/// <param name="sqlBulkCopyOptions"></param>
/// <param name="dbKeyName"></param>
/// <returns></returns>
private int MSSqlBulkInsert(DataTable table, string tableName, SqlBulkCopyOptions sqlBulkCopyOptions = SqlBulkCopyOptions.UseInternalTransaction, string dbKeyName = null)
{
if (!string.IsNullOrEmpty(dbKeyName))
{
Connection.ConnectionString = DBServerProvider.GetConnectionString(dbKeyName);
}
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(Connection.ConnectionString, sqlBulkCopyOptions))
{
sqlBulkCopy.DestinationTableName = tableName;
sqlBulkCopy.BatchSize = table.Rows.Count;
for (int i = 0; i < table.Columns.Count; i++)
{
sqlBulkCopy.ColumnMappings.Add(table.Columns[i].ColumnName, table.Columns[i].ColumnName);
}
sqlBulkCopy.WriteToServer(table);
return table.Rows.Count;
}
}
public int BulkInsert<T>(List<T> entities, string tableName = null,
Expression<Func<T, object>> columns = null,
SqlBulkCopyOptions? sqlBulkCopyOptions = null)
{
DataTable table = entities.ToDataTable(columns, false);
return BulkInsert(table, tableName ?? typeof(T).GetEntityTableName(), sqlBulkCopyOptions);
}
public int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null)
{
if (!string.IsNullOrEmpty(tmpPath))
{
tmpPath = tmpPath.ReplacePath();
}
if (Connection.GetType().Name == "MySqlConnection")
return MySqlBulkInsert(table, tableName, fileName, tmpPath);
else if (Connection.GetType().Name == "NpgsqlConnection")
{
//todo pgsql待实现
throw new Exception("Pgsql的批量插入没实现,可以先把日志start注释跑起来");
}
return MSSqlBulkInsert(table, tableName, sqlBulkCopyOptions ?? SqlBulkCopyOptions.KeepIdentity);
}
/// <summary>
///大批量数据插入,返回成功插入行数
/// </summary>
/// <param name="connectionString">数据库连接字符串</param>
/// <param name="table">数据表</param>
/// <returns>返回成功插入行数</returns>
private int MySqlBulkInsert(DataTable table, string tableName, string fileName = null, string tmpPath = null)
{
if (table.Rows.Count == 0)
return 0;
tmpPath = tmpPath ?? FileHelper.GetCurrentDownLoadPath();
fileName = fileName ?? $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv";
int insertCount = 0;
string csv = DataTableToCsv(table);
FileHelper.WriteFile(tmpPath, fileName, csv);
string path = tmpPath + fileName;
try
{
if (Connection.State == ConnectionState.Closed)
Connection.Open();
using (IDbTransaction tran = Connection.BeginTransaction())
{
MySqlBulkLoader bulk = new MySqlBulkLoader(Connection as MySqlConnection)
{
FieldTerminator = ",",
FieldQuotationCharacter = '"',
EscapeCharacter = '"',
LineTerminator = "\r\n",
FileName = path.ReplacePath(),
NumberOfLinesToSkip = 0,
TableName = tableName,
};
bulk.Columns.AddRange(table.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).ToList());
insertCount = bulk.Load();
tran.Commit();
}
}
catch (Exception ex)
{
throw;
}
finally
{
Connection?.Dispose();
Connection?.Close();
}
return insertCount;
// File.Delete(path);
}
/// <summary>
///将DataTable转换为标准的CSV
/// </summary>
/// <param name="table">数据表</param>
/// <returns>返回标准的CSV</returns>
private string DataTableToCsv(DataTable table)
{
//以半角逗号(即,)作分隔符,列为空也要表达其存在。
//列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。
//列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
StringBuilder sb = new StringBuilder();
DataColumn colum;
Type typeString = typeof(string);
Type typeDate = typeof(DateTime);
foreach (DataRow row in table.Rows)
{
for (int i = 0; i < table.Columns.Count; i++)
{
colum = table.Columns[i];
if (i != 0) sb.Append(",");
if (colum.DataType == typeString && row[colum].ToString().Contains(","))
sb.Append("\"" + row[colum].ToString().Replace("\"", "\"\"") + "\"");
else if (colum.DataType == typeDate)
{
//centos系统里把datatable里的日期转换成了10/18/18 3:26:15 PM格式
bool b = DateTime.TryParse(row[colum].ToString(), out DateTime dt);
sb.Append(b ? dt.ToString("yyyy-MM-dd HH:mm:ss") : "");
}
else sb.Append(row[colum].ToString());
}
sb.AppendLine();
}
return sb.ToString();
}
/// <summary>
/// 返回DataTable
/// </summary>
/// <param name="cmd"></param>
/// <param name="param"></param>
/// <param name="commandType"></param>
/// <returns></returns>
public DataTable GetDataTable(string cmd, object param, CommandType? commandType = null)
{
DataTable table = new DataTable("MyTable");
var reader = ExecuteReader(cmd, param, commandType);
table.Load(reader);
return table;
}
}

@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Tiobon.Core.Common.DB.Dapper.Const;
using Tiobon.Core.Common.DB.Dapper.DBManager;
using Tiobon.Core.Common.DB.Dapper.Enums;
namespace Tiobon.Core.Common.DB.Dapper;
public class DbAccess
{
public static ISqlDapper Instance
{
get
{
return DBServerProvider.SqlDapper;
}
}
public static bool MySql
{
get
{
bool result = false;
if (DBType.Name == DbCurrentType.MySql.ToString())
{
result = true;
}
return result;
}
}
#region 获取SQL插入语句
/// <summary>
/// 获取SQL插入语句
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="columnName">列名</param>
/// <param name="columnValue">列值</param>
/// <returns>SQL插入语句</returns>
public StringBuilder GetInsertSql(string tableName, string columnName, string columnValue)
{
try
{
DbInsert di = null;
string sql = null;
StringBuilder sqls = new StringBuilder();
DbSelect ds = new DbSelect(tableName + " A", "A");
ds.IsInitDefaultValue = false;
ds.Where("A." + columnName, "=", columnValue);
DataTable dt = Instance.GetDataTable(ds.GetSql(), null);
for (int i = 0; i < dt.Rows.Count; i++)
{
di = new DbInsert(tableName, "GetInsertSql");
di.IsInitDefaultValue = false;
for (int j = 0; j < dt.Columns.Count; j++)
{
di.Values(dt.Columns[j].ColumnName, dt.Rows[i][dt.Columns[j].ColumnName].ToString());
}
sql = di.GetSql();
sqls.Append(sql + ";\n");
}
return sqls;
}
catch (Exception) { throw; }
}
#endregion
#region 数据库名称
/// <summary>
/// 数据库名称
/// </summary>
public static string DatabaseName
{
get
{
return Instance.Connection.Database;
}
}
#endregion
public static DataTable GetDataTable(string sql, object param = null, CommandType? commandType = null, bool beginTransaction = false) => Instance.GetDataTable(sql, param, commandType, beginTransaction);
public static async Task<DataTable> GetDataTableAsync(string cmd, object param = null, IDbTransaction transaction = null, CommandType? commandType = null, int? commandTimeout = null) => await Instance.GetDataTableAsync(cmd, param, transaction, commandType, commandTimeout);
public static List<T> QueryList<T>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) where T : class => Instance.QueryList<T>(cmd, param, commandType, beginTransaction);
public static async Task<List<T>> QueryListAsync<T>(string cmd, object param = null, bool beginTransaction = false, CommandType? commandType = null, int? commandTimeout = null) where T : class => await Instance.QueryListAsync<T>(cmd, param, commandType, beginTransaction, commandTimeout);
public static T QueryFirst<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false) where T : class => Instance.QueryFirst<T>(cmd, param, commandType, beginTransaction);
public static async Task<T> QueryFirstAsync<T>(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false, int? commandTimeout = null) where T : class => await Instance.QueryFirstAsync<T>(cmd, param, commandType, beginTransaction, commandTimeout);
public static object ExecuteScalar(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false) => Instance.ExecuteScalar(cmd, param, commandType, beginTransaction);
public static async Task<object> ExecuteScalarAsync(string cmd, object param = null, CommandType? commandType = null, bool beginTransaction = false) => await Instance.ExecuteScalarAsync(cmd, param, commandType, beginTransaction);
public static int ExcuteNonQuery(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) => Instance.ExcuteNonQuery(cmd, param, commandType, beginTransaction);
public static (List<T1>, List<T2>) QueryMultiple<T1, T2>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) => Instance.QueryMultiple<T1, T2>(cmd, param, commandType, beginTransaction);
public static (List<T1>, List<T2>, List<T3>) QueryMultiple<T1, T2, T3>(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) => Instance.QueryMultiple<T1, T2, T3>(cmd, param, commandType, beginTransaction);
public static int ExecuteDML(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null) => Instance.ExecuteDML(cmd, param, commandType, dbTransaction);
public static async Task<int> ExecuteDMLAsync(string cmd, object param, CommandType? commandType = null, IDbTransaction dbTransaction = null) => await Instance.ExecuteDMLAsync(cmd, param, commandType, dbTransaction);
public static int Add<T>(T entity, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = false)
{
return Instance.Add<T>(entity, updateFileds, beginTransaction);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="updateFileds">指定插入的字段</param>
/// <param name="beginTransaction">是否开启事务</param>
/// <returns></returns>
public static int AddRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> addFileds = null, bool beginTransaction = true)
{
return Instance.AddRange<T>(entities, addFileds, beginTransaction);
}
public static int Update<T>(T entity, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = true)
{
return Instance.Update<T>(entity, updateFileds, beginTransaction);
}
/// <summary>
///(根据主键批量更新实体) sqlserver使用的临时表参数化批量更新,mysql待优化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">实体必须带主键</param>
/// <param name="updateFileds">批定更新字段</param>
/// <param name="beginTransaction"></param>
/// <returns></returns>
public static int UpdateRange<T>(IEnumerable<T> entities, Expression<Func<T, object>> updateFileds = null, bool beginTransaction = true)
{
return Instance.UpdateRange<T>(entities, updateFileds, beginTransaction);
}
public static int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null)
{
return Instance.BulkInsert(table, tableName, sqlBulkCopyOptions, fileName, tmpPath);
}
}

@ -0,0 +1,83 @@
using System;
using System.IO;
using System.Text;
using Tiobon.Core.Common.DB.Dapper.Extensions;
namespace Tiobon.Core.Common.DB.Dapper.Utilities;
public class FileHelper : IDisposable
{
public static string GetCurrentDownLoadPath()
{
return ("Download\\").MapPath();
}
#region 取得文件后缀名
/// <summary>
///
/// </summary>
/// <param name="path">路径 </param>
/// <param name="fileName">文件名</param>
/// <param name="content">写入的内容</param>
/// <param name="appendToLast">是否将内容添加到未尾,默认不添加</param>
public static void WriteFile(string path, string fileName, string content, bool appendToLast = false)
{
try
{
path = path.ReplacePath();
fileName = fileName.ReplacePath();
if (!Directory.Exists(path))//如果不存在就创建file文件夹
Directory.CreateDirectory(path);
using (FileStream stream = File.Open(path + fileName, FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] by = Encoding.Default.GetBytes($"-- {DateTime.Now:yyyy-MM-dd HH:mm:ss}" + "\r\n" + content);
if (appendToLast)
{
stream.Position = stream.Length;
}
else
{
stream.SetLength(0);
}
stream.Write(by, 0, by.Length);
}
}
catch (Exception Ex)
{
string error = Ex.Message;
}
}
#endregion
private bool _alreadyDispose = false;
#region 构造函数
public FileHelper()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
~FileHelper()
{
Dispose();
}
protected virtual void Dispose(bool isDisposing)
{
if (_alreadyDispose) return;
_alreadyDispose = true;
}
#endregion
#region IDisposable 成员
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Http;
namespace Tiobon.Core.Common.DB.Dapper.Utilities;
public static class HttpContext
{
private static IHttpContextAccessor _accessor;
public static Microsoft.AspNetCore.Http.HttpContext Current => _accessor.HttpContext;
internal static void Configure(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
}

@ -0,0 +1,15 @@
using System;
namespace Tiobon.Core.Common.DB.Dapper.Utilities;
public class StringHelper
{
public static string Id
{
get
{
Guid id = Guid.NewGuid();
return id.ToString();
//return GuidRandomGenerator.Instance.Generate();
}
}
}

@ -0,0 +1,33 @@
using System;
namespace Tiobon.Core.Common.DB.Dapper;
/// <summary>
///
/// </summary>
public static class UtilConvert
{
/// <summary>
///
/// </summary>
/// <param name="thisValue"></param>
/// <returns></returns>
public static string ObjToString(this object thisValue)
{
if (thisValue != null) return thisValue.ToString().Trim();
return "";
}
/// <summary>
///
/// </summary>
/// <param name="thisValue"></param>
/// <returns></returns>
public static bool ObjToBool(this object thisValue)
{
bool reval = false;
if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval))
{
return reval;
}
return reval;
}
}

@ -84,6 +84,13 @@ namespace Tiobon.Core.Common
FormatValue(fieldName.ToUpper(), s);
}
public void Values(string fieldName, string value)
{
string s = "N'{0}'";
s = string.Format(s, value);
FormatValue(fieldName.ToUpper(), s);
}
public void Values(string fieldName, Guid value)
{
string value1 = value.ToString();
@ -263,7 +270,7 @@ namespace Tiobon.Core.Common
//create_by
var createBy = UserContext.Current.User_Id;
Values("CreatedBy", createBy);
Values("CreatedBy", createBy);
//create_date
DateTime createDate = DateTime.Now;

@ -1,4 +1,4 @@
using SimpleDapper;
using Tiobon.Core.Common.DB.Dapper;
using SqlSugar;
using System.Text;

@ -9,11 +9,14 @@
</ItemGroup>
<ItemGroup>
<Compile Remove="Helper\RSAHelper.cs" />
<Compile Remove="Helper\RSAHelperExtend.cs" />
<Compile Remove="LogHelper\ILoggerHelper.cs" />
<Compile Remove="LogHelper\LogHelper.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.5" />
<PackageReference Include="InitQ" Version="1.0.0.18" />
<PackageReference Include="log4net" Version="2.0.15" />
@ -22,6 +25,7 @@
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="MySql.Data" Version="8.3.0" />
<PackageReference Include="PinYinConverterCore" Version="1.0.2" />
<PackageReference Include="MiniProfiler.Shared" Version="4.3.8" />
<PackageReference Include="RestSharp" Version="110.2.0" />
@ -32,6 +36,7 @@
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="StackExchange.Redis" Version="2.7.4" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.2.0" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
@ -49,10 +54,4 @@
<Folder Include="Core\" />
</ItemGroup>
<ItemGroup>
<Reference Include="SimpleDapper">
<HintPath>..\Lib\SimpleDapper.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

@ -1,5 +1,5 @@
using System.Data;
using SimpleDapper;
using Tiobon.Core.Common.DB.Dapper;
using Tiobon.Core.Model.Models;
using Xunit;

@ -32,12 +32,6 @@
<ProjectReference Include="..\Tiobon.Core.Api\Tiobon.Core.Api.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="SimpleDapper">
<HintPath>..\Lib\SimpleDapper.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Update="WMBlog.db">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

Loading…
Cancel
Save