├── 函数处理.xlsx ├── Resource └── icon.jpg ├── Core.Test ├── appsettings.json ├── appsettings.Development.json ├── Program.cs ├── Core.Test.csproj ├── Properties │ └── launchSettings.json ├── FlowOrder.cs ├── Startup.cs └── Controllers │ └── ValuesController.cs ├── Kogel.Dapper.Extension ├── Entites │ ├── EOrderBy.cs │ ├── EOperateType.cs │ ├── EFuzzyLocation.cs │ ├── DataBaseContext.cs │ ├── Navigation.cs │ ├── DynamicTree.cs │ ├── PageList.cs │ └── JoinAssTable.cs ├── Exception │ └── DapperExtensionException.cs ├── Dapper │ ├── SqlMapper.DontMap.cs │ ├── ExplicitConstructorAttribute.cs │ ├── SqlMapper.DeserializerState.cs │ ├── SqlMapper.IParameterCallbacks.cs │ ├── DataTableHandler.cs │ ├── DynamicParameters.CachedOutputSetters.cs │ ├── SqlDataRecordHandler.cs │ ├── SqlMapper.IParameterLookup.cs │ ├── WrappedDataReader.cs │ ├── SqlMapper.CacheInfo.cs │ ├── SqlMapper.ICustomQueryParameter.cs │ ├── CommandFlags.cs │ ├── SqlMapper.IDynamicParameters.cs │ ├── SqlMapper.LiteralToken.cs │ ├── DynamicParameters.ParamInfo.cs │ ├── SqlMapper.IMemberMap.cs │ ├── SqlMapper.ITypeHandler.cs │ ├── FeatureSupport.cs │ ├── XmlHandlers.cs │ ├── SqlMapper.TypeHandlerCache.cs │ ├── SqlDataRecordListTVPParameter.cs │ ├── UdtTypeHandler.cs │ ├── SqlMapper.ITypeMap.cs │ ├── SqlMapper.DapperTable.cs │ ├── SqlMapper.Link.cs │ ├── CustomPropertyTypeMap.cs │ ├── SimpleMemberMap.cs │ ├── TableValuedParameter.cs │ ├── DbString.cs │ ├── TypeExtensions.cs │ ├── SqlMapper.TypeHandler.cs │ ├── SqlMapper.DapperRowMetaObject.cs │ └── WrappedReader.cs ├── Attributes │ ├── StringLength.cs │ ├── Identity.cs │ ├── BaseAttrbute.cs │ ├── ForeignKey.cs │ └── Display.cs ├── Core │ ├── Interfaces │ │ ├── ICommandSet.cs │ │ ├── IQuerySet.Select.cs │ │ ├── ICodeFirst.cs │ │ ├── IAggregation.cs │ │ ├── ICommand.cs │ │ ├── IQuerySet.Order.cs │ │ ├── IQuerySet.SelectFrom.cs │ │ ├── IDapperSet.cs │ │ └── IQuerySet.Where.cs │ ├── SetQ │ │ ├── QuerySet.Select.cs │ │ ├── QuerySet.Order.cs │ │ ├── Aggregation.cs │ │ ├── QuerySet.SelectFrom.cs │ │ └── QuerySet.Where.cs │ └── SetC │ │ └── CommandSet.cs ├── Extension │ ├── From │ │ └── IBaseEntity.cs │ └── ExpressExpansion.cs ├── Expressions │ ├── ExpressionModifier.cs │ ├── NavigationExpression.cs │ ├── GroupExpression.cs │ ├── ExpressionBuilder.cs │ ├── WhereExpression.cs │ └── UpdateExpression.cs ├── Helper │ ├── TypeHelper.cs │ ├── Function.cs │ ├── Cache │ │ └── EntityCache.cs │ └── VersionCompatible.cs ├── AopProvider.cs └── Kogel.Dapper.Extension.csproj ├── Kogel.Dapper.Extension.Test ├── Dto │ ├── TestDto.cs │ ├── AppConfigDto1.cs │ └── OrderResDto.cs ├── Model │ ├── Test.cs │ ├── Dto │ │ └── FlowOrderDto.cs │ ├── Digiwin │ │ └── TAM_SERIAL_NO_CREATE_BAS.cs │ ├── LikeRecord.cs │ ├── ProductWay.cs │ ├── AppConfig.cs │ ├── FlowOrder.cs │ └── HeadOrder.cs ├── packages.config ├── UnitTest │ ├── Mysql │ │ └── Repository │ │ │ ├── FlowOrderRepository.cs │ │ │ └── IBaseRepository.cs │ ├── Mssql │ │ ├── Command.cs │ │ └── Query.cs │ └── Oracle │ │ ├── Query.cs │ │ └── Command.cs ├── Properties │ ├── AssemblyInfo.cs │ └── app.manifest ├── DbContextTest.cs ├── Program.cs └── App.config ├── README.md ├── Kogel.Repository ├── Entites │ ├── ProviderPool.cs │ ├── ProviderOptions.cs │ ├── ConnectionOptions.cs │ └── ConnectionPool.cs ├── Interfaces │ ├── IUnitOfWork.cs │ └── IBaseRepository.cs ├── Global.cs ├── DependencyInjection.cs └── Kogel.Repository.csproj ├── Kogel.Dapper.Extension.Mssql ├── Kogel.Dapper.Extension.Mssql.csproj ├── DataBase.cs └── Extension │ └── QueryExtension.cs ├── Kogel.Dapper.Extension.MySql ├── Kogel.Dapper.Extension.MySql.csproj ├── DataBase.cs └── Extension │ └── QueryExtension.cs ├── Kogel.Dapper.Extension.Oracle ├── Kogel.Dapper.Extension.Oracle.csproj ├── Extension │ └── QueryExtension.cs └── DataBase.cs ├── Kogel.Dapper.Extension.SQLite ├── Kogel.Dapper.Extension.SQLite.csproj ├── DataBase.cs └── Extension │ └── QueryExtension.cs └── .gitattributes /函数处理.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kogel-net/Kogel.Dapper.Extension/HEAD/函数处理.xlsx -------------------------------------------------------------------------------- /Resource/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kogel-net/Kogel.Dapper.Extension/HEAD/Resource/icon.jpg -------------------------------------------------------------------------------- /Core.Test/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/EOrderBy.cs: -------------------------------------------------------------------------------- 1 | namespace Kogel.Dapper.Extension.Entites 2 | { 3 | public enum EOrderBy 4 | { 5 | Asc = 1, 6 | Desc = -1 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/EOperateType.cs: -------------------------------------------------------------------------------- 1 | namespace Kogel.Dapper.Extension.Entites 2 | { 3 | public enum EOperateType 4 | { 5 | Query, 6 | Command 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Core.Test/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Dto/TestDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Test.Model 8 | { 9 | public class TestDto 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension.Attributes; 7 | 8 | namespace Kogel.Dapper.Extension.Test.Model 9 | { 10 | 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Exception/DapperExtensionException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public class DapperExtensionException : Exception 6 | { 7 | public DapperExtensionException(string msg) : base(msg) 8 | { 9 | 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/EFuzzyLocation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Entites 8 | { 9 | public enum EFuzzyLocation 10 | { 11 | Left, 12 | Right, 13 | Both 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.DontMap.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public static partial class SqlMapper 6 | { 7 | /// 8 | /// Dummy type for excluding from multi-map 9 | /// 10 | public class DontMap : IBaseEntity 11 | { /* hiding constructor */ 12 | public override int Id { get; set; } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/ExplicitConstructorAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | /// 6 | /// Tell Dapper to use an explicit constructor, passing nulls or 0s for all parameters 7 | /// 8 | [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] 9 | public sealed class ExplicitConstructorAttribute : Attribute 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/UnitTest/Mysql/Repository/FlowOrderRepository.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Test.Model; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Test.UnitTest.Mysql.Repository 9 | { 10 | public class FlowOrderRepository : IBaseRepository 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Attributes/StringLength.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Kogel.Dapper.Extension.Attributes 6 | { 7 | public class StringLength : BaseAttrbute 8 | { 9 | /// 10 | /// 字段长度 11 | /// 12 | /// 字段长度 13 | public StringLength(int Length) 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/Dto/FlowOrderDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Test.Model.Dto 8 | { 9 | public class FlowOrderDto 10 | { 11 | public int Id { get; set; } 12 | 13 | 14 | public bool flowOrders1 { get; set; } 15 | 16 | 17 | public bool flowOrders2 { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Attributes/Identity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Kogel.Dapper.Extension.Attributes 6 | { 7 | public class Identity : BaseAttrbute 8 | { 9 | /// 10 | /// 是否自增 11 | /// 12 | public bool IsIncrease { get; set; } 13 | public Identity(bool IsIncrease = true) 14 | { 15 | this.IsIncrease = IsIncrease; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 介绍 3 | 4 | 此框架是Dapper的扩展,效率优于EntityFramwork,并且支持.NetFramework和.NetCore框架 5 | 6 | Koge.Dapper.Extension是一个小型库,通过为POCO添加基本的CRUD操作(获取,插入,更新,删除)来补充Dapper。对于更高级的查询方案,Kogel.Dapper.Extension提供了谓词系统。该库的目的是通过不需要任何属性或基类继承来保持POCO的纯净。 7 | 8 | 通过ClassMapper实现自定义映射。 9 | 10 | 支持Mssql,Oracle,Mysql等数据库 11 | 12 | 支持.net framework4.5,.net core2.0及以上 13 | 14 | 应用层需要引用包Kogel.Dapper.Extension.MsSql(如果数据库是Oracle则引用Kogel.Dapper.Extension.Oracle),Nuget上可以下载安装。 15 | 16 | 文档地址:https://www.cnblogs.com/kogel/p/10805696.html 17 | 18 | 或者百度,谷歌直接搜索Dapper Linq -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Attributes/BaseAttrbute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Kogel.Dapper.Extension.Attributes 6 | { 7 | public class BaseAttrbute : Attribute 8 | { 9 | public string Name { get; set; } 10 | public string Description { get; set; } 11 | 12 | public BaseAttrbute(string Name = null, string Description = null) 13 | { 14 | this.Name = Name; 15 | this.Description = Description; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.DeserializerState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | internal struct DeserializerState 9 | { 10 | public readonly int Hash; 11 | public readonly Func Func; 12 | 13 | public DeserializerState(int hash, Func func) 14 | { 15 | Hash = hash; 16 | Func = func; 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.IParameterCallbacks.cs: -------------------------------------------------------------------------------- 1 | namespace Kogel.Dapper.Extension 2 | { 3 | public static partial class SqlMapper 4 | { 5 | /// 6 | /// Extends IDynamicParameters with facilities for executing callbacks after commands have completed 7 | /// 8 | public interface IParameterCallbacks : IDynamicParameters 9 | { 10 | /// 11 | /// Invoked when the command has executed 12 | /// 13 | void OnCompleted(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/DataTableHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | #if !NETSTANDARD1_3 4 | namespace Kogel.Dapper.Extension 5 | { 6 | internal sealed class DataTableHandler : SqlMapper.ITypeHandler 7 | { 8 | public object Parse(Type destinationType, object value) 9 | { 10 | throw new NotImplementedException(); 11 | } 12 | 13 | public void SetValue(IDbDataParameter parameter, object value) 14 | { 15 | TableValuedParameter.Set(parameter, value as DataTable, null); 16 | } 17 | } 18 | } 19 | #endif -------------------------------------------------------------------------------- /Kogel.Repository/Entites/ProviderPool.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Repository.Entites 9 | { 10 | public class ProviderPool 11 | { 12 | /// 13 | /// 14 | /// 15 | public Func FuncProvider { get; set; } 16 | 17 | /// 18 | /// 自定义名称 19 | /// 20 | public string DbName { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/ICommandSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Kogel.Dapper.Extension.Core.Interfaces 6 | { 7 | public interface ICommandSet : ICommand 8 | { 9 | ICommandSet Where(Expression> predicate); 10 | 11 | ICommandSet Where(string sqlWhere, object param = null); 12 | 13 | ICommandSet WhereIf(bool where, Expression> truePredicate, Expression> falsePredicate); 14 | 15 | ICommandSet ResetTableName(Type type, string tableName); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/DataBaseContext.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.SetC; 2 | using Kogel.Dapper.Extension.Core.SetQ; 3 | using Kogel.Dapper.Extension.Entites; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | public class DataBaseContext : AbstractDataBaseContext 8 | { 9 | public QuerySet QuerySet => (QuerySet)Set; 10 | 11 | public CommandSet CommandSet => (CommandSet)Set; 12 | } 13 | 14 | public abstract class AbstractDataBaseContext 15 | { 16 | public AbstractSet Set { get; set; } 17 | 18 | public EOperateType OperateType { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/DynamicParameters.CachedOutputSetters.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public partial class DynamicParameters 6 | { 7 | // The type here is used to differentiate the cache by type via generics 8 | // ReSharper disable once UnusedTypeParameter 9 | internal static class CachedOutputSetters 10 | { 11 | // Intentional, abusing generics to get our cache splits 12 | // ReSharper disable once StaticMemberInGenericType 13 | public static readonly Hashtable Cache = new Hashtable(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/IQuerySet.Select.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Core.Interfaces 9 | { 10 | public interface IQuerySet : IQuerySet 11 | { 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | IQuery Select(Expression> select); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlDataRecordHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | internal sealed class SqlDataRecordHandler : SqlMapper.ITypeHandler 8 | { 9 | public object Parse(Type destinationType, object value) 10 | { 11 | throw new NotSupportedException(); 12 | } 13 | 14 | public void SetValue(IDbDataParameter parameter, object value) 15 | { 16 | SqlDataRecordListTVPParameter.Set(parameter, value as IEnumerable, null); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.IParameterLookup.cs: -------------------------------------------------------------------------------- 1 | namespace Kogel.Dapper.Extension 2 | { 3 | public static partial class SqlMapper 4 | { 5 | /// 6 | /// Extends IDynamicParameters providing by-name lookup of parameter values 7 | /// 8 | public interface IParameterLookup : IDynamicParameters 9 | { 10 | /// 11 | /// Get the value of the specified parameter (return null if not found) 12 | /// 13 | /// The name of the parameter to get. 14 | object this[string name] { get; } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/WrappedDataReader.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | /// 6 | /// Describes a reader that controls the lifetime of both a command and a reader, 7 | /// exposing the downstream command/reader as properties. 8 | /// 9 | public interface IWrappedDataReader : IDataReader 10 | { 11 | /// 12 | /// Obtain the underlying reader 13 | /// 14 | IDataReader Reader { get; } 15 | /// 16 | /// Obtain the underlying command 17 | /// 18 | IDbCommand Command { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Core.Test/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | 11 | namespace Core.Test 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Kogel.Repository/Entites/ProviderOptions.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Repository.Entites 9 | { 10 | public class ProviderOptions 11 | { 12 | /// 13 | /// 14 | /// 15 | public Func Provider { get; set; } 16 | 17 | /// 18 | /// 数据库名称 19 | /// 20 | public string DbName { get; set; } 21 | 22 | /// 23 | /// 是否是主链接 24 | /// 25 | public bool IsCurrent { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.CacheInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Threading; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | public static partial class SqlMapper 8 | { 9 | internal class CacheInfo 10 | { 11 | public DeserializerState Deserializer { get; set; } 12 | public Func[] OtherDeserializers { get; set; } 13 | public Action ParamReader { get; set; } 14 | private int hitCount; 15 | public int GetHitCount() { return Interlocked.CompareExchange(ref hitCount, 0, 0); } 16 | public void RecordHit() { Interlocked.Increment(ref hitCount); } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Kogel.Repository/Entites/ConnectionOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Repository.Entites 9 | { 10 | /// 11 | /// 12 | /// 13 | public class ConnectionOptions 14 | { 15 | /// 16 | /// 17 | /// 18 | public IDbConnection Connection { get; set; } 19 | 20 | /// 21 | /// 数据库名称 22 | /// 23 | public string DbName { get; set; } 24 | 25 | /// 26 | /// 是否是主链接 27 | /// 28 | public bool IsCurrent { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.ICustomQueryParameter.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public static partial class SqlMapper 6 | { 7 | /// 8 | /// Implement this interface to pass an arbitrary db specific parameter to Dapper 9 | /// 10 | public interface ICustomQueryParameter 11 | { 12 | /// 13 | /// Add the parameter needed to the command before it executes 14 | /// 15 | /// The raw command prior to execution 16 | /// Parameter name 17 | void AddParameter(IDbCommand command, string name); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/CommandFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | /// 6 | /// Additional state flags that control command behaviour 7 | /// 8 | [Flags] 9 | public enum CommandFlags 10 | { 11 | /// 12 | /// No additional flags 13 | /// 14 | None = 0, 15 | /// 16 | /// Should data be buffered before returning? 17 | /// 18 | Buffered = 1, 19 | /// 20 | /// Can async queries be pipelined? 21 | /// 22 | Pipelined = 2, 23 | /// 24 | /// Should the plan cache be bypassed? 25 | /// 26 | NoCache = 4, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.IDynamicParameters.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public static partial class SqlMapper 6 | { 7 | /// 8 | /// Implement this interface to pass an arbitrary db specific set of parameters to Dapper 9 | /// 10 | public interface IDynamicParameters 11 | { 12 | /// 13 | /// Add all the parameters needed to the command just before it executes 14 | /// 15 | /// The raw command prior to execution 16 | /// Information about the query 17 | void AddParameters(IDbCommand command, Identity identity); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Attributes/ForeignKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Attributes 8 | { 9 | /// 10 | /// 导航关联 11 | /// 12 | public class ForeignKey : Attribute 13 | { 14 | /// 15 | /// 索引字段 16 | /// 17 | public string IndexField { get; set; } 18 | /// 19 | /// (导航表)关联字段 20 | /// 21 | public string AssoField { get; set; } 22 | /// 23 | /// 导航关联 24 | /// 25 | /// 索引字段 26 | /// (导航表)关联字段 27 | public ForeignKey(string IndexField, string AssoField) 28 | { 29 | this.IndexField = IndexField; 30 | this.AssoField = AssoField; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/UnitTest/Mssql/Command.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Repository; 2 | using System; 3 | using System.Data.SqlClient; 4 | using Kogel.Dapper.Extension.Attributes; 5 | using Kogel.Dapper.Extension.MsSql; 6 | 7 | namespace Kogel.Dapper.Extension.Test.UnitTest.Mssql 8 | { 9 | public class Command 10 | { 11 | public void Test() 12 | { 13 | 14 | } 15 | } 16 | 17 | /// 18 | /// 19 | /// 20 | [Display(Rename = "test")] 21 | public class Test 22 | { 23 | /// 24 | /// 25 | /// 26 | [Identity] 27 | [Display(Rename = "id")] 28 | public int Id { get; set; } 29 | 30 | /// 31 | /// 32 | /// 33 | [Display(Rename = "name")] 34 | public string Name { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Extension/From/IBaseEntity.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Attributes; 2 | using System; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | /// 7 | /// 父级实体类 8 | /// 9 | /// 10 | /// 11 | public abstract class IBaseEntity : IBaseEntity 12 | { 13 | /// 14 | /// 主键id 15 | /// 16 | [Identity] 17 | public virtual TKey Id { get; set; } 18 | /// 19 | /// 获取主键值 20 | /// 21 | /// 22 | public object GetId() 23 | { 24 | return this.Id; 25 | } 26 | } 27 | 28 | public interface IBaseEntity 29 | { 30 | object GetId(); 31 | } 32 | 33 | public class IBaseEntityDto : IBaseEntity 34 | { 35 | public object GetId() 36 | { 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Core.Test/Core.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/Digiwin/TAM_SERIAL_NO_CREATE_BAS.cs: -------------------------------------------------------------------------------- 1 | using Digiwin.MES.Server.Infrastructure.Core.DataBase.Model; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Test.Model.Digiwin 9 | { 10 | public class TAM_SERIAL_NO_CREATE_BAS : EntityBase 11 | { 12 | /// 13 | /// 设备工序GUID 14 | /// 15 | public string SERIAL_GUID { get; set; } 16 | /// 17 | /// 工装GUID 18 | /// 19 | public string CLASS_GUID { get; set; } 20 | /// 21 | /// 组号 22 | /// 23 | public string GROUP_NO { get; set; } 24 | /// 25 | /// 流水号 26 | /// 27 | public decimal SERIAL_NUMBER { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Core.Test/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:61208", 8 | "sslPort": 44392 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "api/values", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "Core.Test": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "api/values", 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Expressions/ExpressionModifier.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace Kogel.Dapper.Extension.Expressions 4 | { 5 | internal class ExpressionModifier : ExpressionVisitor 6 | { 7 | public ExpressionModifier(Expression newExpression, Expression oldExpression) 8 | { 9 | _newExpression = newExpression; 10 | _oldExpression = oldExpression; 11 | } 12 | 13 | private readonly Expression _newExpression; 14 | private readonly Expression _oldExpression; 15 | 16 | public Expression Replace(Expression node) 17 | { 18 | return Visit(node == _oldExpression ? _newExpression : node); 19 | } 20 | 21 | public static Expression Replace(Expression node, Expression oldExpression, Expression newExpression) 22 | { 23 | return new ExpressionModifier(newExpression, oldExpression).Replace(node); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Kogel.Repository/Interfaces/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Data; 7 | 8 | namespace Kogel.Repository.Interfaces 9 | { 10 | public interface IUnitOfWork : IDisposable 11 | { 12 | /// 13 | /// 数据库连接 14 | /// 15 | IDbConnection Connection { get; } 16 | 17 | /// 18 | /// 工作单元事务 19 | /// 20 | IDbTransaction Transaction { get; set; } 21 | 22 | /// 23 | /// 开启事务 24 | /// 25 | /// 26 | /// 27 | IUnitOfWork BeginTransaction(Action transactionMethod, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted); 28 | 29 | /// 30 | /// 提交 31 | /// 32 | void Commit(); 33 | 34 | /// 35 | /// 回滚 36 | /// 37 | void Rollback(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/SetQ/QuerySet.Select.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Kogel.Dapper.Extension.Core.SetQ 11 | { 12 | public class QuerySet : QuerySet, IQuerySet 13 | { 14 | public QuerySet(IDbConnection conn, SqlProvider sqlProvider) : base(conn, sqlProvider) 15 | { 16 | } 17 | 18 | public QuerySet(IDbConnection conn, SqlProvider sqlProvider, IDbTransaction dbTransaction) : base(conn, sqlProvider, dbTransaction) 19 | { 20 | } 21 | 22 | public IQuery Select(Expression> select) 23 | { 24 | SqlProvider.Context.Set.SelectExpression = select; 25 | return this as IQuery; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/ICodeFirst.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using Kogel.Dapper.Extension.Entites; 3 | 4 | namespace Kogel.Dapper.Extension.Core.Interfaces 5 | { 6 | /// 7 | /// 同步实体到数据库 8 | /// 9 | public interface ICodeFirst 10 | { 11 | /// 12 | /// 同步字段(生成sql) 13 | /// 14 | /// 15 | /// 16 | string SyncField(EntityObject typeEntity, EntityField field); 17 | 18 | /// 19 | /// 同步单个表结构 20 | /// 21 | /// 22 | void SyncTable(EntityObject typeEntity); 23 | 24 | /// 25 | /// 同步整体实体结构 26 | /// 27 | void SyncStructure(); 28 | 29 | /// 30 | /// 转换字段类型 31 | /// 32 | /// 字段类型 33 | /// 长度 34 | /// 35 | string ConversionFieldType(SqlDbType sqlDbType, int length); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/Navigation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Entites 9 | { 10 | /// 11 | /// 导航属性的关联解析实体 12 | /// 13 | public class Navigation 14 | { 15 | public Navigation() 16 | { 17 | //WhereExpressionList = new List(); 18 | } 19 | 20 | /// 21 | /// 属性字段(当前定义的字段) 22 | /// 23 | public string AssoField { get; set; } 24 | /// 25 | /// 关联条件 26 | /// 27 | public string JoinWhere { get; set; } 28 | /// 29 | /// 连接表实体 30 | /// 31 | public Type JsonAssoTable { get; set; } 32 | /// 33 | /// 导航类型(0实体,1列表(集合)) 34 | /// 35 | public NavigationEnum NavigationType { get; set; } 36 | } 37 | 38 | public enum NavigationEnum 39 | { 40 | Model = 0, 41 | List = 1 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Kogel.Repository/Global.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Repository.Entites; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Kogel.Repository 10 | { 11 | /// 12 | /// 全局设置 13 | /// 14 | internal static class Global 15 | { 16 | /// 17 | /// 初始化 18 | /// 19 | static Global() 20 | { 21 | ConnectionPool = new ConcurrentBag(); 22 | ProviderPool = new ConcurrentBag(); 23 | } 24 | 25 | /// 26 | /// 总连接池 (所有连接都会注册到总连接池中,总连接池中不区分主从) 27 | /// 28 | internal static ConcurrentBag ConnectionPool { get; } 29 | 30 | /// 31 | /// 解析方池(总连接池中不区分主从) 32 | /// 33 | internal static ConcurrentBag ProviderPool { get; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/UnitTest/Oracle/Query.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Oracle; 2 | using Kogel.Dapper.Extension.Test.Model; 3 | using Oracle.ManagedDataAccess.Client; 4 | using Kogel.Dapper.Extension.Oracle.Extension; 5 | 6 | namespace Kogel.Dapper.Extension.Test.UnitTest.Oracle 7 | { 8 | public class Query 9 | { 10 | 11 | public void Test() 12 | { 13 | 14 | using (var conn = new OracleConnection("user id=adonis;password=adonis;data source=192.168.0.120:1521/helowin; Pooling=false;")) 15 | { 16 | //EntityCache.Register(new System.Type[] { typeof(FlowOrder), typeof(HeadOrder), typeof(WarehouseOrder) }); 17 | //var codeFirst = new CodeFirst(conn); 18 | //codeFirst.SyncStructure(); 19 | 20 | var flowOrders = conn.QuerySet() 21 | .Where(x => x.CustomerCode == "test") 22 | .Top(2) 23 | .ToList(); 24 | } 25 | 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/DynamicTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | 7 | namespace Kogel.Dapper.Extension.Entites 8 | { 9 | public class DynamicTree 10 | { 11 | public DynamicTree() 12 | { 13 | Operators = ExpressionType.Equal; 14 | ValueType = DbType.String; 15 | } 16 | /// 17 | /// 对应字段的表(默认为空) 18 | /// 19 | public string Table { get; set; } 20 | /// 21 | /// 字段 22 | /// 23 | public string Field { get; set; } 24 | /// 25 | /// 判断方式(13 等于,6 模糊查询,16 大于等于,21 小于等于) 26 | /// 27 | public ExpressionType Operators { get; set; } 28 | /// 29 | /// 判断的值 30 | /// 31 | public string Value { get; set; } 32 | /// 33 | /// 值类型(6 DateTime,11 Int32,16 String) 34 | /// 35 | public DbType ValueType { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Dto/AppConfigDto1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Test.Dto 8 | { 9 | public class AppConfigDto1 10 | { 11 | /// 12 | /// 13 | /// 14 | public int Id { get; set; } 15 | /// 16 | /// 编码(唯一标识) 17 | /// 18 | public string Code { get; set; } 19 | /// 20 | /// 父级id 21 | /// 22 | public int ParentId { get; set; } 23 | /// 24 | /// 标题 25 | /// 26 | public string Title { get; set; } 27 | /// 28 | /// 商场id 29 | /// 30 | public string MarketId { get; set; } 31 | /// 32 | /// 描述 33 | /// 34 | public string Description { get; set; } 35 | /// 36 | /// 父级名称 37 | /// 38 | public string ParentName { get; set; } 39 | /// 40 | /// 41 | /// 42 | public bool IsDelete { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Kogel.Repository/Entites/ConnectionPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Repository.Entites 9 | { 10 | /// 11 | /// 12 | /// 13 | public class ConnectionPool 14 | { 15 | /// 16 | /// 17 | /// 18 | public Func FuncConnection { get; set; } 19 | 20 | /// 21 | /// 连接字符串(内部判断使用) 22 | /// 23 | internal string ConnectionString { get; set; } 24 | 25 | /// 26 | /// 数据库名称(自定义标识) 27 | /// 28 | public string DbName { get; set; } 29 | 30 | /// 31 | /// 数据库名称(实际名称) 32 | /// 33 | public string Database { get; set; } 34 | 35 | /// 36 | /// 数据源地址 37 | /// 38 | public string DataSource { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.LiteralToken.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public static partial class SqlMapper 6 | { 7 | /// 8 | /// Represents a placeholder for a value that should be replaced as a literal value in the resulting sql 9 | /// 10 | internal struct LiteralToken 11 | { 12 | /// 13 | /// The text in the original command that should be replaced 14 | /// 15 | public string Token { get; } 16 | 17 | /// 18 | /// The name of the member referred to by the token 19 | /// 20 | public string Member { get; } 21 | 22 | internal LiteralToken(string token, string member) 23 | { 24 | Token = token; 25 | Member = member; 26 | } 27 | 28 | internal static readonly IList None = new LiteralToken[0]; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/DynamicParameters.ParamInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public partial class DynamicParameters 7 | { 8 | private sealed class ParamInfo 9 | { 10 | public string Name { get; set; } 11 | public object Value { get; set; } 12 | public ParameterDirection ParameterDirection { get; set; } 13 | public DbType? DbType { get; set; } 14 | public int? Size { get; set; } 15 | public IDbDataParameter AttachedParam { get; set; } 16 | internal Action OutputCallback { get; set; } 17 | internal object OutputTarget { get; set; } 18 | internal bool CameFromTemplate { get; set; } 19 | 20 | public byte? Precision { get; set; } 21 | public byte? Scale { get; set; } 22 | /// 23 | /// 是否永存 24 | /// 25 | public bool IsForever { get; set; } = false; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Kogel.Repository/DependencyInjection.cs: -------------------------------------------------------------------------------- 1 | #if NETCOREAPP || NETSTANDARD2_0 2 | using Kogel.Dapper.Extension; 3 | using Kogel.Repository.Interfaces; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using System; 6 | using System.Reflection; 7 | using static Kogel.Repository.RepositoryExtension; 8 | 9 | namespace Kogel.Repository 10 | { 11 | public static class DependencyInjection 12 | { 13 | /// 14 | /// 注册仓储 15 | /// 16 | /// 17 | /// 18 | /// 19 | public static IServiceCollection AddKogelRepository(this IServiceCollection services, Action setup) 20 | { 21 | services.AddTransient((x) => 22 | { 23 | var options = new RepositoryOptionsBuilder(); 24 | setup.Invoke(options); 25 | return options; 26 | }); 27 | services.AddTransient(typeof(IRepository<>), typeof(BaseRepositoryExtension<>)); 28 | return services; 29 | } 30 | } 31 | } 32 | #endif -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Kogel.Dapper.Extension.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Kogel.Dapper.Extension.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("5e18be03-03ce-4732-aa33-7978859bcfeb")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.IMemberMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | /// 9 | /// Implements this interface to provide custom member mapping 10 | /// 11 | public interface IMemberMap 12 | { 13 | /// 14 | /// Source DataReader column name 15 | /// 16 | string ColumnName { get; } 17 | 18 | /// 19 | /// Target member type 20 | /// 21 | Type MemberType { get; } 22 | 23 | /// 24 | /// Target property 25 | /// 26 | PropertyInfo Property { get; } 27 | 28 | /// 29 | /// Target field 30 | /// 31 | FieldInfo Field { get; } 32 | 33 | /// 34 | /// Target constructor parameter 35 | /// 36 | ParameterInfo Parameter { get; } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.ITypeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | /// 9 | /// Implement this interface to perform custom type-based parameter handling and value parsing 10 | /// 11 | public interface ITypeHandler 12 | { 13 | /// 14 | /// Assign the value of a parameter before a command executes 15 | /// 16 | /// The parameter to configure 17 | /// Parameter value 18 | void SetValue(IDbDataParameter parameter, object value); 19 | 20 | /// 21 | /// Parse a database value back to a typed value 22 | /// 23 | /// The value from the database 24 | /// The type to parse to 25 | /// The typed value 26 | object Parse(Type destinationType, object value); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/LikeRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Test.Model 8 | { 9 | /// 10 | /// 评论点赞记录表 11 | /// 12 | public class LikeRecord 13 | { 14 | /// 15 | /// Id 16 | /// 17 | public long Id { get; set; } 18 | /// 19 | /// 评论Id 20 | /// 21 | public long CommentId { get; set; } 22 | /// 23 | /// 用户Id 24 | /// 25 | public long UserId { get; set; } 26 | 27 | /// 28 | /// 评论类型 1=计划 2=文章 29 | /// 30 | public int Type { get; set; } 31 | /// 32 | /// 状态 1=点赞 2=取消点赞 33 | /// 34 | public int Status { get; set; } 35 | /// 36 | /// 创建时间 37 | /// 38 | public DateTime CreateTime { get; set; } 39 | /// 40 | /// 更新时间 41 | /// 42 | public DateTime UpdateTime { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/FeatureSupport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | /// 7 | /// Handles variances in features per DBMS 8 | /// 9 | internal class FeatureSupport 10 | { 11 | private static readonly FeatureSupport 12 | Default = new FeatureSupport(false), 13 | Postgres = new FeatureSupport(true); 14 | 15 | /// 16 | /// Gets the feature set based on the passed connection 17 | /// 18 | /// The connection to get supported features for. 19 | public static FeatureSupport Get(IDbConnection connection) 20 | { 21 | string name = connection?.GetType().Name; 22 | if (string.Equals(name, "npgsqlconnection", StringComparison.OrdinalIgnoreCase)) return Postgres; 23 | return Default; 24 | } 25 | 26 | private FeatureSupport(bool arrays) 27 | { 28 | Arrays = arrays; 29 | } 30 | 31 | /// 32 | /// True if the db supports array columns e.g. Postgresql 33 | /// 34 | public bool Arrays { get; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/IAggregation.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using System; 3 | using System.Linq.Expressions; 4 | 5 | namespace Kogel.Dapper.Extension.Core.Interfaces 6 | { 7 | public interface IAggregation 8 | { 9 | /// 10 | /// 行数 11 | /// 12 | /// 13 | int Count(); 14 | 15 | /// 16 | /// 总和 17 | /// 18 | /// 19 | /// 20 | /// 21 | TResult Sum(Expression> sumExpression); 22 | 23 | /// 24 | /// 最小值 25 | /// 26 | /// 27 | /// 28 | /// 29 | TResult Min(Expression> minExpression); 30 | 31 | /// 32 | /// 最大值 33 | /// 34 | /// 35 | /// 36 | /// 37 | TResult Max(Expression> maxExpression); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Mssql/Kogel.Dapper.Extension.Mssql.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kogel.Dapper.Extension.Mssql 4 | orm;sql;micro-orm 5 | Dapper 6 | orm;sql;micro-orm 7 | Kogel 8 | net451;netstandard2.0;netcoreapp2.1;netcoreapp3.1; 9 | Kogel.Dapper.Extension.Mssql 10 | Kogel.Dapper.Extension.Mssql 11 | true 12 | 3.2.2.6 13 | icon.jpg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | True 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.MySql/Kogel.Dapper.Extension.MySql.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kogel.Dapper.Extension.MySql 4 | orm;sql;micro-orm 5 | Dapper 6 | orm;sql;micro-orm 7 | Kogel 8 | net451;netstandard2.0;netcoreapp2.1;netcoreapp3.1; 9 | Kogel.Dapper.Extension.MySql 10 | Kogel.Dapper.Extension.MySql 11 | true 12 | 3.2.2.6 13 | icon.jpg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | True 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/DbContextTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension; 7 | using Kogel.Dapper.Extension.Test.Model; 8 | using Kogel.Dapper.Extension.MsSql; 9 | 10 | namespace Kogel.Dapper.Extension.Test 11 | { 12 | public class DbContextTest : DbContext 13 | { 14 | public DbSet Comments { get; set; } 15 | /// 16 | /// 配置连接方式 17 | /// 18 | /// 19 | protected override void OnConfiguring(DbContextOptionsBuilder builder) 20 | { 21 | builder = new DbContextOptionsBuilder() 22 | .UseConnectionString("Data Source=42.157.195.21,4344;Initial Catalog=Qx_Sport_Common;User ID=qxdev;Password=qxdev123456;") 23 | .UseSqlProvider(new MsSqlProvider()); 24 | base.OnConfiguring(builder); 25 | } 26 | } 27 | 28 | public class test 29 | { 30 | public void send() 31 | { 32 | using (var ctx = new DbContextTest()) 33 | { 34 | var commentList = ctx.Comments.Select().Where(x => x.UserId.In(new int[] { 1, 2, 3 })).ToList(); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Oracle/Kogel.Dapper.Extension.Oracle.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kogel.Dapper.Extension.Oracle 4 | orm;sql;micro-orm 5 | Dapper 6 | orm;sql;micro-orm 7 | Kogel 8 | net451;netstandard2.0;netcoreapp2.1;netcoreapp3.1; 9 | Kogel.Dapper.Extension.Oracle 10 | Kogel.Dapper.Extension.Oracle 11 | true 12 | 3.2.2.6 13 | icon.jpg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | True 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.SQLite/Kogel.Dapper.Extension.SQLite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kogel.Dapper.Extension.SQLite 4 | orm;sql;micro-orm 5 | Dapper 6 | orm;sql;micro-orm 7 | Kogel 8 | net451;netstandard2.0;netcoreapp2.1;netcoreapp3.1; 9 | Kogel.Dapper.Extension.SQLite 10 | Kogel.Dapper.Extension.SQLite 11 | true 12 | 3.2.2.6 13 | icon.jpg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | True 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/XmlHandlers.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Xml; 3 | using System.Xml.Linq; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | internal abstract class XmlTypeHandler : SqlMapper.StringTypeHandler 8 | { 9 | public override void SetValue(IDbDataParameter parameter, T value) 10 | { 11 | base.SetValue(parameter, value); 12 | parameter.DbType = DbType.Xml; 13 | } 14 | } 15 | 16 | internal sealed class XmlDocumentHandler : XmlTypeHandler 17 | { 18 | protected override XmlDocument Parse(string xml) 19 | { 20 | var doc = new XmlDocument(); 21 | doc.LoadXml(xml); 22 | return doc; 23 | } 24 | 25 | protected override string Format(XmlDocument xml) => xml.OuterXml; 26 | } 27 | 28 | internal sealed class XDocumentHandler : XmlTypeHandler 29 | { 30 | protected override XDocument Parse(string xml) => XDocument.Parse(xml); 31 | protected override string Format(XDocument xml) => xml.ToString(); 32 | } 33 | 34 | internal sealed class XElementHandler : XmlTypeHandler 35 | { 36 | protected override XElement Parse(string xml) => XElement.Parse(xml); 37 | protected override string Format(XElement xml) => xml.ToString(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Oracle/Extension/QueryExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension; 7 | using Kogel.Dapper.Extension.Core.SetQ; 8 | 9 | namespace Kogel.Dapper.Extension.Oracle.Extension 10 | { 11 | public static class QueryExtension 12 | { 13 | //oracle不支持返回多视图对象 14 | /* public static List UpdateSelect(this Query query, Expression> updator) 15 | { 16 | var sqlProvider = query.SqlProvider; 17 | var dbCon = query.DbCon; 18 | var dbTransaction = query.DbTransaction; 19 | sqlProvider.FormatUpdateSelect(updator); 20 | 21 | return dbCon.Query(sqlProvider.SqlString, sqlProvider.Params, dbTransaction).ToList(); 22 | } 23 | 24 | public static async Task> UpdateSelectAsync(this Query query, Expression> updator) 25 | { 26 | var sqlProvider = query.SqlProvider; 27 | var dbCon = query.DbCon; 28 | var dbTransaction = query.DbTransaction; 29 | sqlProvider.FormatUpdateSelect(updator); 30 | 31 | return await dbCon.QueryAsync(sqlProvider.SqlString, sqlProvider.Params, dbTransaction); 32 | } 33 | */ 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/ProductWay.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Attributes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Test.Model 9 | { 10 | [Display(Rename = "Lige_ProductWay")] 11 | public class ProductWay : IBaseEntity 12 | { 13 | /// 14 | /// 15 | /// 16 | [Identity] 17 | public override int Id { get; set; } 18 | /// 19 | /// 同步的標識 20 | /// 21 | public string Code { get; set; } 22 | /// 23 | /// 積分 24 | /// 25 | public decimal Point { get; set; } 26 | /// 27 | /// 金額 28 | /// 29 | public decimal Price { get; set; } 30 | /// 31 | /// 商品代碼 32 | /// 33 | public string ProductCode { get; set; } 34 | /// 35 | /// 36 | /// 37 | public string CreateUser { get; set; } 38 | /// 39 | /// 40 | /// 41 | public DateTime CreateDate { get; set; } 42 | /// 43 | /// 44 | /// 45 | public string UpdateUser { get; set; } 46 | /// 47 | /// 48 | /// 49 | public DateTime UpdateDate { get; set; } 50 | /// 51 | /// 52 | /// 53 | public bool IsDelete { get; set; } 54 | /// 55 | /// 支付方式類型 56 | /// 57 | public int ProductWayType { get; set; } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Expressions/NavigationExpression.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Kogel.Dapper.Extension.Expressions 10 | { 11 | public class NavigationExpression : ExpressionVisitor 12 | { 13 | /// 14 | /// sql指令 15 | /// 16 | public string SqlCmd { get; set; } 17 | /// 18 | /// 参数 19 | /// 20 | public DynamicParameters Param { get; set; } 21 | /// 22 | /// 返回类型 23 | /// 24 | public Type ReturnType { get; set; } 25 | /// 26 | /// 条件表达式 27 | /// 28 | public List WhereExpression { get; set; } 29 | public NavigationExpression(Expression expression) 30 | { 31 | Visit(expression); 32 | } 33 | 34 | protected override Expression VisitMethodCall(MethodCallExpression node) 35 | { 36 | var nodeExpression = node; 37 | if (node.Arguments.Count() != 0) 38 | { 39 | var argumentExp = node.Arguments[0] as MethodCallExpression; 40 | if (argumentExp != null) 41 | { 42 | nodeExpression = argumentExp; 43 | } 44 | } 45 | var subquery = new SubqueryExpression(nodeExpression); 46 | this.SqlCmd = subquery.SqlCmd; 47 | this.Param = subquery.Param; 48 | this.ReturnType = subquery.ReturnType; 49 | this.WhereExpression = subquery.WhereExpression; 50 | return node; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/ICommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | 7 | namespace Kogel.Dapper.Extension.Core.Interfaces 8 | { 9 | public interface ICommand 10 | { 11 | int Update(T entity, string[] excludeFields = null, int timeout = 120); 12 | 13 | int Update(IEnumerable entities, IDbDataAdapter adapter, string[] excludeFields = null, int timeout = 120); 14 | 15 | int Update(Expression> updateExpression); 16 | 17 | Task UpdateAsync(T entity, string[] excludeFields = null, int timeout = 120); 18 | 19 | Task UpdateAsync(IEnumerable entities, string[] excludeFields = null, int timeout = 120); 20 | 21 | Task UpdateAsync(Expression> updateExpression); 22 | 23 | int Delete(); 24 | 25 | int Delete(T model); 26 | 27 | Task DeleteAsync(); 28 | 29 | Task DeleteAsync(T model); 30 | 31 | int Insert(T entity, string[] excludeFields = null); 32 | 33 | long InsertIdentity(T entity, string[] excludeFields = null); 34 | 35 | int Insert(IEnumerable entities, string[] excludeFields = null, int timeout = 120); 36 | 37 | Task InsertAsync(T entity, string[] excludeFields = null); 38 | 39 | Task InsertIdentityAsync(T entity, string[] excludeFields = null); 40 | 41 | Task InsertAsync(IEnumerable entities, string[] excludeFields = null, int timeout = 120); 42 | 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Program.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.SetQ; 2 | using Kogel.Dapper.Extension.Extension.From; 3 | //using Kogel.Dapper.Extension.MySql; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Linq.Expressions; 8 | using MySql.Data.MySqlClient; 9 | using System.Linq; 10 | using System.Data.SqlClient; 11 | using Kogel.Dapper.Extension.MsSql; 12 | using Kogel.Dapper.Extension.Entites; 13 | using System.Collections.Concurrent; 14 | 15 | namespace Kogel.Dapper.Extension.Test 16 | { 17 | class Program 18 | { 19 | static void Main(string[] args) 20 | { 21 | /* #region mssql单元测试 22 | var mssqlQuery = new UnitTest.Mssql.Query(); 23 | //mssqlQuery.Test(); 24 | 25 | var mssqlCommand = new UnitTest.Mssql.Command(); 26 | mssqlCommand.Test(); 27 | #endregion*/ 28 | 29 | #region mysql单元测试 30 | var mysqlQuery = new UnitTest.Mysql.Query(); 31 | mysqlQuery.Test(); 32 | 33 | EntityCache.Register("Kogel.Dapper.Extension.Test.Models"); 34 | 35 | //var mysqlCommand = new UnitTest.Mysql.Command(); 36 | //mysqlCommand.Test(); 37 | #endregion 38 | 39 | //stopwatch.Stop(); 40 | 41 | //#region oracle单元测试 42 | //var oracleQuery = new UnitTest.Oracle.Query(); 43 | //oracleQuery.Test(); 44 | 45 | //var oracleCommand = new UnitTest.Oracle.Command(); 46 | //oracleCommand.Test(); 47 | //#endregion 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/IQuerySet.Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Core.Interfaces 9 | { 10 | public partial interface IQuerySet 11 | { 12 | /// 13 | /// 顺序 14 | /// 15 | /// 16 | /// 17 | IQuerySet OrderBy(Expression> field); 18 | 19 | /// 20 | /// 倒序 21 | /// 22 | /// 23 | /// 24 | IQuerySet OrderByDescing(Expression> field); 25 | 26 | /// 27 | /// 顺序 28 | /// 29 | /// 30 | /// 31 | /// 32 | IQuerySet OrderBy(Expression> field); 33 | 34 | /// 35 | /// 倒叙 36 | /// 37 | /// 38 | /// 39 | /// 40 | IQuerySet OrderByDescing(Expression> field); 41 | 42 | /// 43 | /// 字符串拼接排序 44 | /// 45 | /// 46 | /// 47 | IQuerySet OrderBy(string orderBy); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/AppConfig.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Attributes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension.Test.Model 9 | { 10 | [Display(Rename = "Lige_AppConfig", AsName = "AppConfig")] 11 | public class AppConfig 12 | { 13 | /// 14 | /// 15 | /// 16 | [Identity] 17 | public int Id { get; set; } 18 | /// 19 | /// 编码(唯一标识) 20 | /// 21 | public string Code { get; set; } 22 | /// 23 | /// 父级id 24 | /// 25 | public int ParentId { get; set; } 26 | /// 27 | /// 标题 28 | /// 29 | public string Title { get; set; } 30 | /// 31 | /// 商场id 32 | /// 33 | public string MarketId { get; set; } 34 | /// 35 | /// 描述 36 | /// 37 | public string Description { get; set; } 38 | /// 39 | /// 40 | /// 41 | public string CreateUser { get; set; } 42 | /// 43 | /// 44 | /// 45 | public DateTime CreateDate { get; set; } 46 | /// 47 | /// 48 | /// 49 | public string UpdateUser { get; set; } 50 | /// 51 | /// 52 | /// 53 | public DateTime UpdateDate { get; set; } 54 | /// 55 | /// 56 | /// 57 | public bool IsDelete { get; set; } 58 | 59 | } 60 | 61 | /// 62 | /// 多表联查扩展类(当一次查询用到多次相同表时使用) 63 | /// 64 | [Display(Rename = "Lige_AppConfig", AsName = "AppConfig1")] 65 | public class AppConfig1 : AppConfig 66 | { 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/UnitTest/Mysql/Repository/IBaseRepository.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Repository; 2 | using MySql.Data.MySqlClient; 3 | 4 | namespace Kogel.Dapper.Extension.Test.UnitTest.Mysql.Repository 5 | { 6 | public class IBaseRepository : BaseRepository 7 | { 8 | /// 9 | /// 配置连接 10 | /// 11 | /// 12 | public override void OnConfiguring(RepositoryOptionsBuilder builder) 13 | { 14 | builder.BuildConnection(x => new MySqlConnection(@"server=192.168.0.120;port=3306;user id=root;password=123456;database=gc_fps_receivable;Persist Security Info=True;")) 15 | .BuildConnection(x => new MySqlConnection(@"server=192.168.87.141;port=63307;user id=fps_dbuser_dev;password=kxx44cuvlmjluqncju; 16 | persistsecurityinfo=True;database=gc_fps_receivable_dev_2021_0;SslMode=none;Persist Security Info=True;"), "fps_2021") 17 | .BuildConnection(x => new MySqlConnection(@"server=192.168.87.203;port=63307;user id=fps_user;password=1Nl7C9CQRWhsEy1E; 18 | persistsecurityinfo=True;database=gc_fps_receivable_test;SslMode=none;Persist Security Info=True;"), "fps_test") 19 | .BuildConnection(x => new MySqlConnection(@"server=192.168.87.203;port=63307;user id=fps_user;password=1Nl7C9CQRWhsEy1E; 20 | persistsecurityinfo=True;database=gc_fps_receivable_test_2021_0;SslMode=none;Persist Security Info=True;"), "fps_test_2021") 21 | .BuildAutoSyncStructure(false) 22 | .BuildProvider(new MySqlProvider()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/IQuerySet.SelectFrom.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Extension.From; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Kogel.Dapper.Extension.Core.Interfaces 10 | { 11 | /// 12 | /// 多表查询扩展 13 | /// 14 | public partial interface IQuerySet 15 | { 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | IQuery Select(Expression> select); 23 | 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | ISelectFrom From(); 31 | 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | ISelectFrom From(); 40 | 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | ISelectFrom From(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.TypeHandlerCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Data; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | public static partial class SqlMapper 8 | { 9 | /// 10 | /// Not intended for direct usage 11 | /// 12 | /// The type to have a cache for. 13 | [Obsolete(ObsoleteInternalUsageOnly, false)] 14 | #if !NETSTANDARD1_3 15 | [Browsable(false)] 16 | #endif 17 | [EditorBrowsable(EditorBrowsableState.Never)] 18 | public static class TypeHandlerCache 19 | { 20 | /// 21 | /// Not intended for direct usage. 22 | /// 23 | /// The object to parse. 24 | [Obsolete(ObsoleteInternalUsageOnly, true)] 25 | public static T Parse(object value) => (T)handler.Parse(typeof(T), value); 26 | 27 | /// 28 | /// Not intended for direct usage. 29 | /// 30 | /// The parameter to set a value for. 31 | /// The value to set. 32 | [Obsolete(ObsoleteInternalUsageOnly, true)] 33 | public static void SetValue(IDbDataParameter parameter, object value) => handler.SetValue(parameter, value); 34 | 35 | internal static void SetHandler(ITypeHandler handler) 36 | { 37 | #pragma warning disable 618 38 | TypeHandlerCache.handler = handler; 39 | #pragma warning restore 618 40 | } 41 | 42 | private static ITypeHandler handler; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/PageList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | /// 6 | /// 分页实体类 7 | /// 8 | /// 9 | public class PageList 10 | { 11 | /// 12 | /// 13 | /// 14 | /// 页码 15 | /// 页项 16 | /// 总数 17 | /// 元素 18 | public PageList(int pageIndex, int pageSize, int totalCount, List items) 19 | { 20 | Total = totalCount; 21 | PageSize = pageSize; 22 | PageIndex = pageIndex; 23 | Items = items; 24 | TotalPage = Total % PageSize == 0 ? Total / PageSize : Total / PageSize + 1; 25 | } 26 | 27 | /// 28 | /// 总数 29 | /// 30 | public int Total { get; } 31 | 32 | /// 33 | /// 元素 34 | /// 35 | public List Items { get; } 36 | 37 | /// 38 | /// 页项 39 | /// 40 | public int PageSize { get; } 41 | 42 | /// 43 | /// 页码 44 | /// 45 | public int PageIndex { get; } 46 | 47 | /// 48 | /// 总页数 49 | /// 50 | public int TotalPage { get; } 51 | 52 | /// 53 | /// 是否有上一页 54 | /// 55 | public bool HasPrev => PageIndex > 1; 56 | 57 | /// 58 | /// 是否有下一页 59 | /// 60 | public bool HasNext => PageIndex < TotalPage; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/SetQ/QuerySet.Order.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.Interfaces; 2 | using Kogel.Dapper.Extension.Entites; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Linq.Expressions; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Kogel.Dapper.Extension.Core.SetQ 12 | { 13 | /// 14 | /// 排序 15 | /// 16 | /// 17 | public partial class QuerySet : Aggregation, IQuerySet 18 | { 19 | public IQuerySet OrderBy(Expression> field) 20 | { 21 | if (field != null) 22 | OrderbyExpressionList.Add(field, EOrderBy.Asc); 23 | return this; 24 | } 25 | 26 | public IQuerySet OrderBy(Expression> field) 27 | { 28 | if (field != null) 29 | OrderbyExpressionList.Add(field, EOrderBy.Asc); 30 | return this; 31 | } 32 | 33 | /// 34 | public IQuerySet OrderByDescing(Expression> field) 35 | { 36 | if (field != null) 37 | OrderbyExpressionList.Add(field, EOrderBy.Desc); 38 | return this; 39 | } 40 | 41 | public IQuerySet OrderByDescing(Expression> field) 42 | { 43 | if (field != null) 44 | OrderbyExpressionList.Add(field, EOrderBy.Desc); 45 | return this; 46 | } 47 | 48 | public IQuerySet OrderBy(string orderBy) 49 | { 50 | if (!string.IsNullOrEmpty(orderBy)) 51 | OrderbyBuilder.Append(orderBy); 52 | return this; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlDataRecordListTVPParameter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data; 3 | using System.Linq; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | /// 8 | /// Used to pass a IEnumerable<SqlDataRecord> as a SqlDataRecordListTVPParameter 9 | /// 10 | internal sealed class SqlDataRecordListTVPParameter : SqlMapper.ICustomQueryParameter 11 | { 12 | private readonly IEnumerable data; 13 | private readonly string typeName; 14 | /// 15 | /// Create a new instance of . 16 | /// 17 | /// The data records to convert into TVPs. 18 | /// The parameter type name. 19 | public SqlDataRecordListTVPParameter(IEnumerable data, string typeName) 20 | { 21 | this.data = data; 22 | this.typeName = typeName; 23 | } 24 | 25 | void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name) 26 | { 27 | var param = command.CreateParameter(); 28 | param.ParameterName = name; 29 | Set(param, data, typeName); 30 | command.Parameters.Add(param); 31 | } 32 | 33 | internal static void Set(IDbDataParameter parameter, IEnumerable data, string typeName) 34 | { 35 | parameter.Value = data != null && data.Any() ? data : null; 36 | if (parameter is System.Data.SqlClient.SqlParameter sqlParam) 37 | { 38 | sqlParam.SqlDbType = SqlDbType.Structured; 39 | sqlParam.TypeName = typeName; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/UdtTypeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | #if !NETSTANDARD1_3 && !NETSTANDARD2_0 9 | /// 10 | /// A type handler for data-types that are supported by the underlying provider, but which need 11 | /// a well-known UdtTypeName to be specified 12 | /// 13 | public class UdtTypeHandler : ITypeHandler 14 | { 15 | private readonly string udtTypeName; 16 | /// 17 | /// Creates a new instance of UdtTypeHandler with the specified . 18 | /// 19 | /// The user defined type name. 20 | public UdtTypeHandler(string udtTypeName) 21 | { 22 | if (string.IsNullOrEmpty(udtTypeName)) throw new ArgumentException("Cannot be null or empty", udtTypeName); 23 | this.udtTypeName = udtTypeName; 24 | } 25 | 26 | object ITypeHandler.Parse(Type destinationType, object value) 27 | { 28 | return value is DBNull ? null : value; 29 | } 30 | 31 | void ITypeHandler.SetValue(IDbDataParameter parameter, object value) 32 | { 33 | #pragma warning disable 0618 34 | parameter.Value = SanitizeParameterValue(value); 35 | #pragma warning restore 0618 36 | if (parameter is System.Data.SqlClient.SqlParameter && !(value is DBNull)) 37 | { 38 | ((System.Data.SqlClient.SqlParameter)parameter).SqlDbType = SqlDbType.Udt; 39 | ((System.Data.SqlClient.SqlParameter)parameter).UdtTypeName = udtTypeName; 40 | } 41 | } 42 | } 43 | #endif 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Kogel.Repository/Kogel.Repository.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kogel.Repository 4 | orm;sql;micro-orm 5 | Dapper 6 | orm;sql;micro-orm 7 | Kogel 8 | net451;netstandard2.0;netcoreapp2.1;netcoreapp3.1; 9 | Kogel.Repository 10 | Kogel.Repository 11 | true 12 | 3.2.2.10 13 | icon.jpg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 3.1.1 28 | 29 | 30 | 31 | 32 | 2.1.1 33 | 34 | 35 | 36 | 37 | 3.1.1 38 | 39 | 40 | 41 | 42 | True 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Expressions/GroupExpression.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using Kogel.Dapper.Extension.Core.Interfaces; 3 | using Kogel.Dapper.Extension; 4 | using Kogel.Dapper.Extension.Extension; 5 | using Kogel.Dapper.Extension.Entites; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Linq.Expressions; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace Kogel.Dapper.Extension.Expressions 14 | { 15 | /// 16 | /// 解析分组 17 | /// 18 | public class GroupExpression: BaseExpressionVisitor 19 | { 20 | #region sql指令 21 | private readonly StringBuilder _sqlCmd; 22 | /// 23 | /// sql指令 24 | /// 25 | public string SqlCmd => _sqlCmd.ToString(); 26 | /// 27 | /// 参数 28 | /// 29 | public new DynamicParameters Param; 30 | #endregion 31 | public GroupExpression(LambdaExpression expression, string prefix, SqlProvider provider) : base(provider) 32 | { 33 | this._sqlCmd = new StringBuilder(); 34 | this.Param = new DynamicParameters(); 35 | //当前定义的查询返回对象 36 | EntityObject entity = EntityCache.QueryEntity(expression.Body.Type); 37 | var newExpression = expression.Body as NewExpression; 38 | foreach (var argument in newExpression.Arguments) 39 | { 40 | base.SpliceField.Clear(); 41 | base.Param = new DynamicParameters(); 42 | if (_sqlCmd.Length != 0) 43 | _sqlCmd.Append(","); 44 | //返回类型 45 | var returnProperty = entity.Properties[base.Index]; 46 | //实体类型 47 | Type entityType; 48 | //验证是实体类或者是泛型 49 | if (ExpressionExtension.IsAnyBaseEntity(returnProperty.PropertyType, out entityType)) 50 | { 51 | throw new DapperExtensionException("GroupBy不支持导航属性!"); 52 | } 53 | else 54 | { 55 | //值对象 56 | Visit(argument); 57 | _sqlCmd.Append($" {base.SpliceField} "); 58 | Param.AddDynamicParams(base.Param); 59 | } 60 | base.Index++; 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/SetQ/Aggregation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Linq.Expressions; 4 | using Kogel.Dapper.Extension; 5 | using Kogel.Dapper.Extension.Core.Interfaces; 6 | using Kogel.Dapper.Extension.Extension; 7 | 8 | namespace Kogel.Dapper.Extension.Core.SetQ 9 | { 10 | /// 11 | /// 聚合 12 | /// 13 | /// 14 | public abstract class Aggregation : Query, IAggregation 15 | { 16 | protected Aggregation(IDbConnection conn, SqlProvider sqlProvider) : base(conn, sqlProvider) 17 | { 18 | 19 | } 20 | IDbTransaction dbTransaction; 21 | protected Aggregation(IDbConnection conn, SqlProvider sqlProvider, IDbTransaction dbTransaction) : base(conn, sqlProvider, dbTransaction) 22 | { 23 | this.dbTransaction = dbTransaction; 24 | } 25 | 26 | /// 27 | public int Count() 28 | { 29 | SqlProvider.FormatCount(); 30 | return DbCon.QuerySingleOrDefault(SqlProvider.SqlString, SqlProvider.Params, dbTransaction); 31 | } 32 | 33 | /// 34 | public TResult Sum(Expression> sumExpression) 35 | { 36 | SqlProvider.FormatSum(sumExpression); 37 | return DbCon.QuerySingleOrDefault(SqlProvider.SqlString, SqlProvider.Params, dbTransaction); 38 | } 39 | 40 | public TResult Max(Expression> maxExpression) 41 | { 42 | SqlProvider.FormatMax(maxExpression); 43 | return DbCon.QuerySingleOrDefault(SqlProvider.SqlString, SqlProvider.Params, dbTransaction); 44 | } 45 | 46 | public TResult Min(Expression> minExpression) 47 | { 48 | SqlProvider.FormatMin(minExpression); 49 | return DbCon.QuerySingleOrDefault(SqlProvider.SqlString, SqlProvider.Params, dbTransaction); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.ITypeMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | /// 9 | /// Implement this interface to change default mapping of reader columns to type members 10 | /// 11 | public interface ITypeMap 12 | { 13 | /// 14 | /// Finds best constructor 15 | /// 16 | /// DataReader column names 17 | /// DataReader column types 18 | /// Matching constructor or default one 19 | ConstructorInfo FindConstructor(string[] names, Type[] types); 20 | 21 | /// 22 | /// Returns a constructor which should *always* be used. 23 | /// 24 | /// Parameters will be default values, nulls for reference types and zero'd for value types. 25 | /// 26 | /// Use this class to force object creation away from parameterless constructors you don't control. 27 | /// 28 | ConstructorInfo FindExplicitConstructor(); 29 | 30 | /// 31 | /// Gets mapping for constructor parameter 32 | /// 33 | /// Constructor to resolve 34 | /// DataReader column name 35 | /// Mapping implementation 36 | IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName); 37 | 38 | /// 39 | /// Gets member mapping for column 40 | /// 41 | /// DataReader column name 42 | /// Mapping implementation 43 | IMemberMap GetMember(string columnName); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Mssql/DataBase.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using Kogel.Dapper.Extension.Core.Interfaces; 3 | using Kogel.Dapper.Extension.Core.SetC; 4 | using Kogel.Dapper.Extension.Core.SetQ; 5 | 6 | namespace Kogel.Dapper.Extension.MsSql 7 | { 8 | public static class DataBase 9 | { 10 | /// 11 | /// 查询 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static IQuerySet QuerySet(this IDbConnection sqlConnection) 17 | { 18 | return new QuerySet(sqlConnection, new MsSqlProvider()); 19 | } 20 | 21 | /// 22 | /// 查询(带事务) 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static IQuerySet QuerySet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 29 | { 30 | return new QuerySet(sqlConnection, new MsSqlProvider(), dbTransaction); 31 | } 32 | 33 | /// 34 | /// 编辑 35 | /// 36 | /// 37 | /// 38 | /// 39 | public static ICommandSet CommandSet(this IDbConnection sqlConnection) 40 | { 41 | return new CommandSet(sqlConnection, new MsSqlProvider()); 42 | } 43 | 44 | /// 45 | /// 编辑(带事务) 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | public static ICommandSet CommandSet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 52 | { 53 | return new CommandSet(sqlConnection, new MsSqlProvider(), dbTransaction); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.DapperTable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | private sealed class DapperTable 9 | { 10 | private string[] fieldNames; 11 | private readonly Dictionary fieldNameLookup; 12 | 13 | internal string[] FieldNames => fieldNames; 14 | 15 | public DapperTable(string[] fieldNames) 16 | { 17 | this.fieldNames = fieldNames ?? throw new ArgumentNullException(nameof(fieldNames)); 18 | 19 | fieldNameLookup = new Dictionary(fieldNames.Length, StringComparer.Ordinal); 20 | // if there are dups, we want the **first** key to be the "winner" - so iterate backwards 21 | for (int i = fieldNames.Length - 1; i >= 0; i--) 22 | { 23 | string key = fieldNames[i]; 24 | if (key != null) fieldNameLookup[key] = i; 25 | } 26 | } 27 | 28 | internal int IndexOfName(string name) 29 | { 30 | return (name != null && fieldNameLookup.TryGetValue(name, out int result)) ? result : -1; 31 | } 32 | 33 | internal int AddField(string name) 34 | { 35 | if (name == null) throw new ArgumentNullException(nameof(name)); 36 | if (fieldNameLookup.ContainsKey(name)) throw new InvalidOperationException("Field already exists: " + name); 37 | int oldLen = fieldNames.Length; 38 | Array.Resize(ref fieldNames, oldLen + 1); // yes, this is sub-optimal, but this is not the expected common case 39 | fieldNames[oldLen] = name; 40 | fieldNameLookup[name] = oldLen; 41 | return oldLen; 42 | } 43 | 44 | internal bool FieldExists(string key) => key != null && fieldNameLookup.ContainsKey(key); 45 | 46 | public int FieldCount => fieldNames.Length; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.SQLite/DataBase.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using Kogel.Dapper.Extension.Core.Interfaces; 3 | using Kogel.Dapper.Extension.Core.SetC; 4 | using Kogel.Dapper.Extension.Core.SetQ; 5 | 6 | namespace Kogel.Dapper.Extension.SQLite 7 | { 8 | public static class DataBase 9 | { 10 | /// 11 | /// 查询 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static IQuerySet QuerySet(this IDbConnection sqlConnection) 17 | { 18 | return new QuerySet(sqlConnection, new SQLiteProvider()); 19 | } 20 | 21 | /// 22 | /// 查询(带事务) 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static IQuerySet QuerySet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 29 | { 30 | return new QuerySet(sqlConnection, new SQLiteProvider(), dbTransaction); 31 | } 32 | 33 | /// 34 | /// 编辑 35 | /// 36 | /// 37 | /// 38 | /// 39 | public static ICommandSet CommandSet(this IDbConnection sqlConnection) 40 | { 41 | return new CommandSet(sqlConnection, new SQLiteProvider()); 42 | } 43 | 44 | /// 45 | /// 编辑(带事务) 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | public static ICommandSet CommandSet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 52 | { 53 | return new CommandSet(sqlConnection, new SQLiteProvider(), dbTransaction); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Helper/TypeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Kogel.Dapper.Extension.Helper 5 | { 6 | internal static class TypeHelper 7 | { 8 | public static Type FindIEnumerable(Type seqType) 9 | { 10 | if (seqType == null || seqType == typeof(string)) 11 | return null; 12 | if (seqType.IsArray) 13 | return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType()); 14 | if (seqType.IsGenericTypes()) 15 | { 16 | foreach (var arg in seqType.GetGenericArguments()) 17 | { 18 | var ienum = typeof(IEnumerable<>).MakeGenericType(arg); 19 | if (ienum.IsAssignableFrom(seqType)) 20 | { 21 | return ienum; 22 | } 23 | } 24 | } 25 | Type[] ifaces = seqType.GetInterfaces(); 26 | if (ifaces.Length > 0) 27 | { 28 | foreach (Type iface in ifaces) 29 | { 30 | Type ienum = FindIEnumerable(iface); 31 | if (ienum != null) return ienum; 32 | } 33 | } 34 | if (seqType.BaseTypes() != null && seqType.BaseTypes() != typeof(object)) 35 | { 36 | return FindIEnumerable(seqType.BaseTypes()); 37 | } 38 | return null; 39 | } 40 | 41 | public static bool IsNullableType(Type type) 42 | { 43 | return type != null && type.IsGenericTypes() && type.GetGenericTypeDefinition() == typeof(Nullable<>); 44 | } 45 | 46 | public static bool IsNullAssignable(Type type) 47 | { 48 | return !type.IsValueTypes() || IsNullableType(type); 49 | } 50 | 51 | public static Type GetNonNullableType(Type type) 52 | { 53 | if (IsNullableType(type)) 54 | { 55 | return type.GetGenericArguments()[0]; 56 | } 57 | return type; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Extension/ExpressExpansion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public static class ExpressExpansion 6 | { 7 | public static bool In(this int input, int[] array) 8 | { 9 | return true; 10 | } 11 | public static bool In(this long input, long[] array) 12 | { 13 | return true; 14 | } 15 | public static bool In(this string input, string[] array) 16 | { 17 | return true; 18 | } 19 | public static bool In(this Guid input, Guid[] array) 20 | { 21 | return true; 22 | } 23 | public static bool NotIn(this int input, int[] array) 24 | { 25 | return true; 26 | } 27 | public static bool NotIn(this long input, long[] array) 28 | { 29 | return true; 30 | } 31 | public static bool NotIn(this string input, string[] array) 32 | { 33 | return true; 34 | } 35 | public static bool NotIn(this Guid input, Guid[] array) 36 | { 37 | return true; 38 | } 39 | public static bool IsNull(this object input) 40 | { 41 | return true; 42 | } 43 | public static bool IsNotNull(this object input) 44 | { 45 | return true; 46 | } 47 | public static bool Between(this int input,int from,int to) 48 | { 49 | return true; 50 | } 51 | public static bool Between(this long input, long from, long to) 52 | { 53 | return true; 54 | } 55 | public static bool Between(this DateTime input, DateTime from, DateTime to) 56 | { 57 | return true; 58 | } 59 | } 60 | /// 61 | /// 聚合函数 62 | /// 63 | public class Group 64 | { 65 | public static int Count(T field) 66 | { 67 | return 0; 68 | } 69 | public static T Sum(T field) 70 | { 71 | return default(T); 72 | } 73 | public static T Max(T field) 74 | { 75 | return default(T); 76 | } 77 | public static T Min(T field) 78 | { 79 | return default(T); 80 | } 81 | public static T Avg(T field) 82 | { 83 | return default(T); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.MySql/DataBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using Kogel.Dapper.Extension.Core.Interfaces; 4 | using Kogel.Dapper.Extension.Core.SetC; 5 | using Kogel.Dapper.Extension.Core.SetQ; 6 | using Kogel.Dapper.Extension.Entites; 7 | 8 | namespace Kogel.Dapper.Extension.MySql 9 | { 10 | public static class DataBase 11 | { 12 | /// 13 | /// 查询 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static IQuerySet QuerySet(this IDbConnection sqlConnection) 19 | { 20 | return new QuerySet(sqlConnection, new MySqlProvider()); 21 | } 22 | 23 | /// 24 | /// 查询(带事务) 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | public static IQuerySet QuerySet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 31 | { 32 | return new QuerySet(sqlConnection, new MySqlProvider(), dbTransaction); 33 | } 34 | 35 | /// 36 | /// 编辑 37 | /// 38 | /// 39 | /// 40 | /// 41 | public static ICommandSet CommandSet(this IDbConnection sqlConnection) 42 | { 43 | return new CommandSet(sqlConnection, new MySqlProvider()); 44 | } 45 | 46 | /// 47 | /// 编辑(带事务) 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | public static ICommandSet CommandSet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 54 | { 55 | return new CommandSet(sqlConnection, new MySqlProvider(), dbTransaction); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/IDapperSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | using Kogel.Dapper.Extension.Entites; 6 | using Kogel.Dapper.Extension; 7 | 8 | namespace Kogel.Dapper.Extension 9 | { 10 | public abstract class AbstractSet 11 | { 12 | /// 13 | /// 数据解析提供方 14 | /// 15 | public SqlProvider SqlProvider; 16 | 17 | /// 18 | /// 表类型 19 | /// 20 | public Type TableType { get; set; } 21 | 22 | /// 23 | /// [已弃用]只用来生成对象 24 | /// 25 | internal LambdaExpression WhereExpression { get; set; } 26 | 27 | /// 28 | /// 条件表达式对象 29 | /// 30 | internal List WhereExpressionList { get; set; } 31 | 32 | /// 33 | /// 表达式排序集合 34 | /// 35 | internal Dictionary OrderbyExpressionList { get; set; } 36 | 37 | /// 38 | /// 字符串排序 39 | /// 40 | internal StringBuilder OrderbyBuilder { get; set; } 41 | 42 | /// 43 | /// 字段查询对象 44 | /// 45 | public LambdaExpression SelectExpression { get; set; } 46 | 47 | /// 48 | /// 是否锁表(with(nolock)) 49 | /// 50 | public bool NoLock { get; set; } 51 | 52 | /// 53 | /// sql字符串对象 54 | /// 55 | internal StringBuilder WhereBuilder { get; set; } 56 | 57 | /// 58 | /// sql参数对象 59 | /// 60 | internal DynamicParameters Params { get => SqlProvider.Params; set => SqlProvider.Params.AddDynamicParams(value); } 61 | 62 | /// 63 | /// 分组表达式对象 64 | /// 65 | internal List GroupExpressionList { get; set; } 66 | 67 | /// 68 | /// 分组聚合条件 69 | /// 70 | internal List HavingExpressionList { get; set; } 71 | 72 | /// 73 | /// 是否去重 74 | /// 75 | public bool IsDistinct { get; set; } 76 | 77 | /// 78 | /// 是否排除在工作单元外 79 | /// 80 | public bool IsExcludeUnitOfWork { get; set; } 81 | 82 | /// 83 | /// 返回行数 84 | /// 85 | public int? TopNum { get; set; } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Dto/OrderResDto.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using Lige.Model; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace Lige.ViewModel.APP.Shopping 8 | { 9 | /// 10 | /// 订单列表返回 11 | /// 12 | public class OrderResDto 13 | { 14 | /// 15 | /// 16 | /// 17 | public int Id { get; set; } 18 | /// 19 | /// 订单号 20 | /// 21 | public string OrderNo { get; set; } 22 | /// 23 | /// 订单创建时间 24 | /// 25 | public DateTime OrderTime { get; set; } 26 | /// 27 | /// 订单状态 28 | /// 29 | public int Status { get; set; } 30 | /// 31 | /// 总金额 32 | /// 33 | public decimal Amount { get; set; } 34 | /// 35 | /// 总积分 36 | /// 37 | public decimal Point { get; set; } 38 | /// 39 | /// 是否存在明细 40 | /// 41 | public bool IsAnyOrderDetail { get; set; } 42 | /// 43 | /// 44 | /// 45 | public OrderDetail DetailList { get; set; } 46 | /// 47 | /// 订单明细 48 | /// 49 | public List OrderDetailList { get; set; } 50 | } 51 | public class test : IBaseEntity 52 | { 53 | public override int Id { get; set; } 54 | } 55 | /// 56 | /// 订单明细 57 | /// 58 | public class OrderDetailResDto: test 59 | { 60 | /// 61 | /// 62 | /// 63 | public override int Id { get; set; } 64 | /// 65 | /// 名称 66 | /// 67 | public string Name { get; set; } 68 | /// 69 | /// 价钱 70 | /// 71 | public decimal Price { get; set; } 72 | /// 73 | /// 积分 74 | /// 75 | public decimal Point { get; set; } 76 | /// 77 | /// 件数 78 | /// 79 | public int Qty { get; set; } 80 | /// 81 | /// 礼品图片 82 | /// 83 | public string ImgUrl { get; set; } 84 | /// 85 | /// 原价 86 | /// 87 | public decimal OriginalPrice { get; set; } 88 | /// 89 | /// 原积分 90 | /// 91 | public decimal OriginalPoint { get; set; } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/SetQ/QuerySet.SelectFrom.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.Interfaces; 2 | using Kogel.Dapper.Extension.Extension.From; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Kogel.Dapper.Extension.Core.SetQ 11 | { 12 | /// 13 | /// 多表查询扩展 14 | /// 15 | /// 16 | public partial class QuerySet 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | public IQuery Select(Expression> select) 25 | { 26 | var query = new Query(this.DbCon, this.SqlProvider, this.DbTransaction); 27 | query.SqlProvider.Context.Set.SelectExpression = select; 28 | return query; 29 | } 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | public ISelectFrom From() 38 | { 39 | return new ISelectFrom(this); 40 | } 41 | 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | public ISelectFrom From() 50 | { 51 | return new ISelectFrom(this); 52 | } 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | public ISelectFrom From() 63 | { 64 | return new ISelectFrom(this); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/Interfaces/IQuerySet.Where.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Entites; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Kogel.Dapper.Extension.Core.Interfaces 10 | { 11 | public partial interface IQuerySet 12 | { 13 | /// 14 | /// 查询条件 15 | /// 16 | /// 17 | /// 18 | IQuerySet Where(Expression> predicate); 19 | 20 | /// 21 | /// 查询条件 22 | /// 23 | /// 24 | /// 25 | /// 26 | IQuerySet Where(Expression> predicate); 27 | 28 | /// 29 | /// 查询条件 30 | /// 31 | /// 32 | /// 33 | IQuerySet Where(Dictionary dynamicTree); 34 | 35 | /// 36 | /// 查询条件 37 | /// 38 | /// 39 | /// 40 | /// 41 | IQuerySet Where(string sqlWhere, object param = null); 42 | 43 | /// 44 | /// 带前置条件的Where判断 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | IQuerySet WhereIf(bool where, Expression> truePredicate, Expression> falsePredicate); 52 | 53 | /// 54 | /// 带前置条件的Where判断 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | IQuerySet WhereIf(bool where, Expression> truePredicate, Expression> falsePredicate); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Attributes/Display.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Data; 5 | 6 | namespace Kogel.Dapper.Extension.Attributes 7 | { 8 | /// 9 | /// 10 | /// 11 | public class Display : BaseAttrbute 12 | { 13 | /// 14 | /// 是否需要隐射该字段 15 | /// 16 | public bool IsField { get; set; } 17 | 18 | /// 19 | /// 重命名(数据库隐射名称(默认为类名)) 20 | /// 21 | public string Rename { get; set; } 22 | 23 | /// 24 | /// 名称空间(例如sqlserver中的dbo) 25 | /// 26 | public string Schema { get; set; } 27 | 28 | /// 29 | /// 指定 as 名称 30 | /// 31 | public string AsName { get; set; } 32 | 33 | /// 34 | /// 数据库字段类型 35 | /// 36 | public SqlDbType SqlDbType { get; set; } 37 | 38 | /// 39 | /// 长度 40 | /// 41 | public int Length { get; set; } 42 | 43 | /// 44 | /// 是否允许为空 45 | /// 46 | public bool? IfNull { get; set; } 47 | 48 | /// 49 | /// 默认值 50 | /// 51 | public object DefaultValue { get; set; } 52 | 53 | /// 54 | /// 描述字段特性 55 | /// 56 | /// 名称 57 | /// 描述 58 | /// 设置对应数据库名称 59 | /// 命名空间(sqlserver默认dbo) 60 | /// 重命名 as xxx 61 | /// 是否是表关联字段(实体类为True) 62 | /// 数据库字段类型 63 | /// 字段长度 64 | /// 是否为空 65 | /// 字段默认值 66 | public Display(string Name = null, string Description = null, string Rename = null, string Schema = null, 67 | string AsName = null, bool IsField = true, SqlDbType SqlDbType = SqlDbType.Structured, int Length = 0, 68 | bool IfNull = default, object DefaultValue = null) 69 | { 70 | this.Name = Name; 71 | this.Description = Description; 72 | this.IsField = IsField; 73 | this.Rename = string.IsNullOrEmpty(Rename) ? Name : Rename; 74 | this.Schema = Schema; 75 | this.AsName = AsName; 76 | this.SqlDbType = SqlDbType; 77 | this.Length = Length; 78 | this.IfNull = IfNull; 79 | this.DefaultValue = DefaultValue; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Oracle/DataBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using Kogel.Dapper.Extension; 4 | using Kogel.Dapper.Extension.Core.Interfaces; 5 | using Kogel.Dapper.Extension.Core.SetC; 6 | using Kogel.Dapper.Extension.Core.SetQ; 7 | using Kogel.Dapper.Extension.Entites; 8 | using Kogel.Dapper.Extension.Oracle.Extension; 9 | 10 | namespace Kogel.Dapper.Extension.Oracle 11 | { 12 | public static class DataBase 13 | { 14 | static DataBase() 15 | { 16 | //注册bool解析 17 | SqlMapper.RemoveTypeMap(typeof(bool)); 18 | SqlMapper.AddTypeHandler(typeof(bool), new BoolTypeHanlder()); 19 | } 20 | 21 | /// 22 | /// 查询 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static IQuerySet QuerySet(this IDbConnection sqlConnection) 28 | { 29 | return new QuerySet(sqlConnection, new OracleSqlProvider()); 30 | } 31 | 32 | /// 33 | /// 查询(带事务) 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | public static IQuerySet QuerySet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 40 | { 41 | return new QuerySet(sqlConnection, new OracleSqlProvider(), dbTransaction); 42 | } 43 | 44 | /// 45 | /// 编辑 46 | /// 47 | /// 48 | /// 49 | /// 50 | public static ICommandSet CommandSet(this IDbConnection sqlConnection) 51 | { 52 | return new CommandSet(sqlConnection, new OracleSqlProvider()); 53 | } 54 | 55 | /// 56 | /// 编辑(带事务) 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | public static ICommandSet CommandSet(this IDbConnection sqlConnection, IDbTransaction dbTransaction) 63 | { 64 | return new CommandSet(sqlConnection, new OracleSqlProvider(), dbTransaction); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/AopProvider.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using System.Threading; 3 | 4 | #if NET45 || NET451 5 | using System.Runtime.Remoting.Messaging; 6 | #endif 7 | 8 | 9 | namespace Kogel.Dapper.Extension 10 | { 11 | public class AopProvider 12 | { 13 | /// 14 | /// 事件模型定义 15 | /// 16 | /// 17 | public delegate void EventHander(ref CommandDefinition command); 18 | 19 | /// 20 | /// 执行前 21 | /// 22 | public event EventHander OnExecuting; 23 | 24 | /// 25 | /// 执行后 26 | /// 27 | public event EventHander OnExecuted; 28 | 29 | /// 30 | /// 触发执行前 31 | /// 32 | /// 33 | internal void InvokeExecuting(ref CommandDefinition definition) 34 | { 35 | this.OnExecuting?.Invoke(ref definition); 36 | } 37 | /// 38 | /// 触发执行后 39 | /// 40 | /// 41 | internal void InvokeExecuted(ref CommandDefinition definition) 42 | { 43 | this.OnExecuted?.Invoke(ref definition); 44 | } 45 | 46 | #if NET45 || NET451 47 | //private static ThreadLocal _aop = new ThreadLocal(); 48 | #else 49 | private static AsyncLocal _aop = new AsyncLocal(); 50 | #endif 51 | 52 | /// 53 | /// 获取当前线程唯一Aop 54 | /// 55 | /// 56 | public static AopProvider Get() 57 | { 58 | #if NET45 || NET451 59 | string contextKey = typeof(AopProvider).FullName; 60 | var _aop = CallContext.LogicalGetData(contextKey); 61 | if (_aop == null) 62 | { 63 | _aop = new AopProvider(); 64 | CallContext.LogicalSetData(contextKey, _aop); 65 | } 66 | return _aop as AopProvider; 67 | #else 68 | lock (_aop) 69 | { 70 | if (_aop.Value == null) 71 | { 72 | //_aop = new ThreadLocal(); 73 | _aop.Value = new AopProvider(); 74 | } 75 | return _aop.Value; 76 | } 77 | #endif 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/UnitTest/Mssql/Query.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.MsSql; 2 | using Kogel.Dapper.Extension; 3 | using System.Data.SqlClient; 4 | using Kogel.Dapper.Extension.Test.Model; 5 | using System; 6 | using Kogel.Dapper.Extension.Attributes; 7 | using Kogel.Dapper.Extension; 8 | using System.Data; 9 | 10 | namespace Kogel.Dapper.Extension.Test.UnitTest.Mssql 11 | { 12 | public class Query 13 | { 14 | 15 | public void Test() 16 | { 17 | SqlMapper.RemoveTypeMap(typeof(Guid)); 18 | SqlMapper.AddTypeHandler(typeof(Guid), new GuidTypeHanlder1()); 19 | using (var conn = new SqlConnection("server=localhost;database=Lige;user=sa;password=!RisingupTech/././.;Connection Timeout=60;")) 20 | { 21 | //var aaa = Guid.NewGuid().ToString(); 22 | var guid = Guid.Parse("25661F78-7113-4BD1-91D4-0B42FC570789"); 23 | var test = conn.QuerySet() 24 | .Where(x => x.Id == guid) 25 | .Get(x => new 26 | { 27 | x.Id 28 | }); 29 | } 30 | 31 | 32 | 33 | } 34 | 35 | } 36 | 37 | public class GuidTypeHanlder1 : SqlMapper.TypeHandler 38 | { 39 | public override void SetValue(IDbDataParameter parameter, Guid value) 40 | { 41 | parameter.Size = 32; 42 | parameter.DbType = DbType.Object; 43 | //parameter.Value = value.ToString(); 44 | parameter.Value = value; 45 | } 46 | 47 | public override Guid Parse(object value) 48 | { 49 | //return Guid.Parse((string)value); 50 | return Convert(value); 51 | } 52 | 53 | internal static Guid Convert(object value) 54 | { 55 | if (value.GetType().Name.Contains("Guid")) 56 | { 57 | return (Guid)value; 58 | } 59 | else 60 | { 61 | return Guid.Parse(value.ToString()); 62 | } 63 | } 64 | } 65 | 66 | /// 67 | /// 68 | /// 69 | [Display(Rename = "test")] 70 | public class TestModel 71 | { 72 | /// 73 | /// 74 | /// 75 | public Guid Id { get; set; } 76 | 77 | /// 78 | /// 79 | /// 80 | public string Name { get; set; } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.Link.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | 3 | namespace Kogel.Dapper.Extension 4 | { 5 | public static partial class SqlMapper 6 | { 7 | /// 8 | /// This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), 9 | /// and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE** 10 | /// equality. The type is fully thread-safe. 11 | /// 12 | /// The type to cache. 13 | /// The value type of the cache. 14 | internal class Link where TKey : class 15 | { 16 | public static bool TryGet(Link link, TKey key, out TValue value) 17 | { 18 | while (link != null) 19 | { 20 | if ((object)key == (object)link.Key) 21 | { 22 | value = link.Value; 23 | return true; 24 | } 25 | link = link.Tail; 26 | } 27 | value = default(TValue); 28 | return false; 29 | } 30 | 31 | public static bool TryAdd(ref Link head, TKey key, ref TValue value) 32 | { 33 | bool tryAgain; 34 | do 35 | { 36 | var snapshot = Interlocked.CompareExchange(ref head, null, null); 37 | if (TryGet(snapshot, key, out TValue found)) 38 | { // existing match; report the existing value instead 39 | value = found; 40 | return false; 41 | } 42 | var newNode = new Link(key, value, snapshot); 43 | // did somebody move our cheese? 44 | tryAgain = Interlocked.CompareExchange(ref head, newNode, snapshot) != snapshot; 45 | } while (tryAgain); 46 | return true; 47 | } 48 | 49 | private Link(TKey key, TValue value, Link tail) 50 | { 51 | Key = key; 52 | Value = value; 53 | Tail = tail; 54 | } 55 | 56 | public TKey Key { get; } 57 | public TValue Value { get; } 58 | public Link Tail { get; } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Helper/Function.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Kogel.Dapper.Extension 9 | { 10 | /// 11 | /// 函数列表 12 | /// 13 | public static class Function 14 | { 15 | #region 聚合函数 16 | public static int Count(T countExpression) => default; 17 | 18 | public static T Sum(T sumExpression) => default; 19 | 20 | public static T Max(T maxExpression) => default; 21 | 22 | public static T Min(T minExpression) => default; 23 | 24 | public static T Avg(T avgExpression) => default; 25 | #endregion 26 | 27 | #region 基础函数 28 | 29 | /// 30 | /// 左模糊 31 | /// 32 | /// 33 | /// 34 | /// 35 | public static bool StartsWith(this string left, string right) => default; 36 | 37 | /// 38 | /// 右模糊 39 | /// 40 | /// 41 | /// 42 | /// 43 | public static bool EndsWith(this string left, string right) => default; 44 | 45 | /// 46 | /// 拼接(oracle使用,mssql可以直接使用+号) 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | public static T Concat(T left, T right) => default; 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | public static T IfNull(T left, T right) => default; 62 | 63 | /// 64 | /// 拼接sql 65 | /// 66 | /// 67 | /// 68 | public static T ConcatSql(string sql) => default; 69 | 70 | /// 71 | /// 拼接sql 72 | /// 73 | /// 74 | /// 75 | /// 76 | public static T ConcatSql(string sql, object param) => default; 77 | #endregion 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Expressions/ExpressionBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace Kogel.Dapper.Extension.Expressions 7 | { 8 | public static class ExpressionBuilder 9 | { 10 | /// 11 | /// 默认True条件 12 | /// 13 | /// 14 | /// 15 | public static Expression> Init() 16 | { 17 | return expression => true; 18 | } 19 | 20 | public static Expression> And(this Expression> first, 21 | Expression> second) 22 | { 23 | return first.Compose(second, Expression.AndAlso); 24 | } 25 | 26 | public static Expression> Or(this Expression> first, 27 | Expression> second) 28 | { 29 | return first.Compose(second, Expression.OrElse); 30 | } 31 | 32 | private static Expression Compose(this Expression first, Expression second, 33 | Func merge 34 | ) 35 | { 36 | var map = first.Parameters 37 | .Select((oldParam, index) => new { oldParam, newParam = second.Parameters[index] }) 38 | .ToDictionary(p => p.newParam, p => p.oldParam); 39 | 40 | var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); 41 | 42 | return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); 43 | } 44 | } 45 | 46 | internal class ParameterRebinder : ExpressionVisitor 47 | { 48 | readonly Dictionary _parameterMap; 49 | 50 | ParameterRebinder(Dictionary map) 51 | { 52 | _parameterMap = map ?? new Dictionary(); 53 | } 54 | 55 | public static Expression ReplaceParameters(Dictionary map, 56 | Expression newParameters) 57 | { 58 | return new ParameterRebinder(map).Visit(newParameters); 59 | } 60 | 61 | protected override Expression VisitParameter(ParameterExpression newParameters) 62 | { 63 | if (_parameterMap.TryGetValue(newParameters, out var replacement)) 64 | { 65 | newParameters = replacement; 66 | } 67 | 68 | return base.VisitParameter(newParameters); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Kogel.Dapper.Extension.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kogel.Dapper.Extension 4 | orm;sql;micro-orm 5 | Dapper 6 | orm;sql;micro-orm 7 | Kogel 8 | net451;netstandard2.0;netcoreapp2.1;netcoreapp3.1; 9 | Kogel.Dapper.Extension 10 | Kogel.Dapper.Extension 11 | true 12 | 3.2.2.6 13 | icon.jpg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 4.3.0 27 | 28 | 29 | 4.3.0 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 4.3.0 49 | 50 | 51 | 4.3.0 52 | 53 | 54 | 55 | 56 | 57 | True 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/CustomPropertyTypeMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | /// 7 | /// Implements custom property mapping by user provided criteria (usually presence of some custom attribute with column to member mapping) 8 | /// 9 | public sealed class CustomPropertyTypeMap : SqlMapper.ITypeMap 10 | { 11 | private readonly Type _type; 12 | private readonly Func _propertySelector; 13 | 14 | /// 15 | /// Creates custom property mapping 16 | /// 17 | /// Target entity type 18 | /// Property selector based on target type and DataReader column name 19 | public CustomPropertyTypeMap(Type type, Func propertySelector) 20 | { 21 | _type = type ?? throw new ArgumentNullException(nameof(type)); 22 | _propertySelector = propertySelector ?? throw new ArgumentNullException(nameof(propertySelector)); 23 | } 24 | 25 | /// 26 | /// Always returns default constructor 27 | /// 28 | /// DataReader column names 29 | /// DataReader column types 30 | /// Default constructor 31 | public ConstructorInfo FindConstructor(string[] names, Type[] types) => 32 | _type.GetConstructor(new Type[0]); 33 | 34 | /// 35 | /// Always returns null 36 | /// 37 | /// 38 | public ConstructorInfo FindExplicitConstructor() => null; 39 | 40 | /// 41 | /// Not implemented as far as default constructor used for all cases 42 | /// 43 | /// 44 | /// 45 | /// 46 | public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName) 47 | { 48 | throw new NotSupportedException(); 49 | } 50 | 51 | /// 52 | /// Returns property based on selector strategy 53 | /// 54 | /// DataReader column name 55 | /// Poperty member map 56 | public SqlMapper.IMemberMap GetMember(string columnName) 57 | { 58 | var prop = _propertySelector(_type, columnName); 59 | return prop != null ? new SimpleMemberMap(columnName, prop) : null; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.SQLite/Extension/QueryExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension.Core.Interfaces; 7 | using Kogel.Dapper.Extension.Core.SetC; 8 | 9 | namespace Kogel.Dapper.Extension.SQLite 10 | { 11 | public static class QueryExtension 12 | { 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | public static List UpdateSelect(this ICommandSet query, Expression> updator) 21 | { 22 | return UpdateSelect(query as CommandSet, updator); 23 | } 24 | 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | public static List UpdateSelect(this CommandSet query, Expression> updator) 33 | { 34 | var sqlProvider = query.SqlProvider; 35 | var dbCon = query.DbCon; 36 | var dbTransaction = query.DbTransaction; 37 | sqlProvider.FormatUpdateSelect(updator); 38 | return dbCon.Query(sqlProvider.SqlString, sqlProvider.Params, dbTransaction).ToList(); 39 | } 40 | 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | public static async Task> UpdateSelectAsync(this ICommandSet query, Expression> updator) 49 | { 50 | return await UpdateSelectAsync(query as CommandSet, updator); 51 | } 52 | 53 | /// 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | public static async Task> UpdateSelectAsync(this CommandSet query, Expression> updator) 61 | { 62 | var sqlProvider = query.SqlProvider; 63 | var dbCon = query.DbCon; 64 | var dbTransaction = query.DbTransaction; 65 | sqlProvider.FormatUpdateSelect(updator); 66 | return (await dbCon.QueryAsync(sqlProvider.SqlString, sqlProvider.Params, dbTransaction)).ToList(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Expressions/WhereExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | using System.Text; 3 | using Kogel.Dapper.Extension; 4 | using Kogel.Dapper.Extension.Core.Interfaces; 5 | using System.Linq; 6 | 7 | namespace Kogel.Dapper.Extension.Expressions 8 | { 9 | /// 10 | /// 解析查询条件 11 | /// 12 | public sealed class WhereExpression : WhereExpressionVisitor 13 | { 14 | #region sql指令 15 | private readonly StringBuilder _sqlCmd; 16 | /// 17 | /// sql指令 18 | /// 19 | public string SqlCmd { get; } 20 | /// 21 | /// 参数 22 | /// 23 | public new DynamicParameters Param { get; } 24 | #endregion 25 | /// 26 | /// 解析条件对象 27 | /// 28 | /// 表达式 29 | /// 参数标记 30 | /// 31 | public WhereExpression(LambdaExpression expression, string prefix, SqlProvider provider) : base(provider) 32 | { 33 | this._sqlCmd = new StringBuilder(100); 34 | this.Param = new DynamicParameters(); 35 | this.providerOption = provider.ProviderOption; 36 | base.Prefix = prefix; 37 | //开始解析对象 38 | Visit(expression); 39 | //开始拼接成条件 40 | this._sqlCmd.Append(base.SpliceField); 41 | this.SqlCmd = " AND " + this._sqlCmd.ToString(); 42 | this.Param.AddDynamicParams(base.Param); 43 | } 44 | 45 | /// 46 | /// 解析二元表达式 47 | /// 48 | /// 49 | /// 50 | protected override Expression VisitBinary(BinaryExpression node) 51 | { 52 | var binaryWhere = new BinaryExpressionVisitor(node, base.Provider, 0, base.Prefix); 53 | this._sqlCmd.Append(binaryWhere.SpliceField); 54 | base.Param.AddDynamicParams(binaryWhere.Param); 55 | return node; 56 | } 57 | 58 | /// 59 | /// 解析!不等于(!里只能包含一个条件) 60 | /// 61 | /// 62 | /// 63 | protected override Expression VisitUnary(UnaryExpression node) 64 | { 65 | if (node.NodeType == ExpressionType.Not) 66 | { 67 | base.SpliceField.Append(" Not ("); 68 | Visit(node.Operand); 69 | base.SpliceField.Append(") "); 70 | } 71 | else 72 | { 73 | Visit(node.Operand); 74 | } 75 | return node; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SimpleMemberMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | /// 7 | /// Represents simple member map for one of target parameter or property or field to source DataReader column 8 | /// 9 | internal sealed class SimpleMemberMap : SqlMapper.IMemberMap 10 | { 11 | /// 12 | /// Creates instance for simple property mapping 13 | /// 14 | /// DataReader column name 15 | /// Target property 16 | public SimpleMemberMap(string columnName, PropertyInfo property) 17 | { 18 | ColumnName = columnName ?? throw new ArgumentNullException(nameof(columnName)); 19 | Property = property ?? throw new ArgumentNullException(nameof(property)); 20 | } 21 | 22 | /// 23 | /// Creates instance for simple field mapping 24 | /// 25 | /// DataReader column name 26 | /// Target property 27 | public SimpleMemberMap(string columnName, FieldInfo field) 28 | { 29 | ColumnName = columnName ?? throw new ArgumentNullException(nameof(columnName)); 30 | Field = field ?? throw new ArgumentNullException(nameof(field)); 31 | } 32 | 33 | /// 34 | /// Creates instance for simple constructor parameter mapping 35 | /// 36 | /// DataReader column name 37 | /// Target constructor parameter 38 | public SimpleMemberMap(string columnName, ParameterInfo parameter) 39 | { 40 | ColumnName = columnName ?? throw new ArgumentNullException(nameof(columnName)); 41 | Parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); 42 | } 43 | 44 | /// 45 | /// DataReader column name 46 | /// 47 | public string ColumnName { get; } 48 | 49 | /// 50 | /// Target member type 51 | /// 52 | public Type MemberType => Field?.FieldType ?? Property?.PropertyType ?? Parameter?.ParameterType; 53 | 54 | /// 55 | /// Target property 56 | /// 57 | public PropertyInfo Property { get; } 58 | 59 | /// 60 | /// Target field 61 | /// 62 | public FieldInfo Field { get; } 63 | 64 | /// 65 | /// Target constructor parameter 66 | /// 67 | public ParameterInfo Parameter { get; } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.MySql/Extension/QueryExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension; 7 | using Kogel.Dapper.Extension.Core.Interfaces; 8 | using Kogel.Dapper.Extension.Core.SetC; 9 | 10 | namespace Kogel.Dapper.Extension.MySql 11 | { 12 | public static class QueryExtension 13 | { 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static List UpdateSelect(this ICommandSet query, Expression> updator) 22 | { 23 | return UpdateSelect(query as CommandSet, updator); 24 | } 25 | 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | public static List UpdateSelect(this CommandSet query, Expression> updator) 34 | { 35 | var sqlProvider = query.SqlProvider; 36 | var dbCon = query.DbCon; 37 | var dbTransaction = query.DbTransaction; 38 | sqlProvider.FormatUpdateSelect(updator); 39 | return dbCon.Query(sqlProvider.SqlString, sqlProvider.Params, dbTransaction).ToList(); 40 | } 41 | 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | public static async Task> UpdateSelectAsync(this ICommandSet query, Expression> updator) 50 | { 51 | return await UpdateSelectAsync(query as CommandSet, updator); 52 | } 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | public static async Task> UpdateSelectAsync(this CommandSet query, Expression> updator) 62 | { 63 | var sqlProvider = query.SqlProvider; 64 | var dbCon = query.DbCon; 65 | var dbTransaction = query.DbTransaction; 66 | sqlProvider.FormatUpdateSelect(updator); 67 | return (await dbCon.QueryAsync(sqlProvider.SqlString, sqlProvider.Params, dbTransaction)).ToList(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Mssql/Extension/QueryExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension; 7 | using Kogel.Dapper.Extension.Core.Interfaces; 8 | using Kogel.Dapper.Extension.Core.SetC; 9 | using Kogel.Dapper.Extension.Core.SetQ; 10 | 11 | namespace Kogel.Dapper.Extension.MsSql 12 | { 13 | public static class QueryExtension 14 | { 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | public static List UpdateSelect(this ICommandSet query, Expression> updator) 23 | { 24 | return UpdateSelect(query as CommandSet, updator); 25 | } 26 | 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static List UpdateSelect(this CommandSet query, Expression> updator) 35 | { 36 | var sqlProvider = query.SqlProvider; 37 | var dbCon = query.DbCon; 38 | var dbTransaction = query.DbTransaction; 39 | sqlProvider.FormatUpdateSelect(updator); 40 | return dbCon.Query(sqlProvider.SqlString, sqlProvider.Params, dbTransaction).ToList(); 41 | } 42 | 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | public static async Task> UpdateSelectAsync(this ICommandSet query, Expression> updator) 51 | { 52 | return await UpdateSelectAsync(query as CommandSet, updator); 53 | } 54 | 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | public static async Task> UpdateSelectAsync(this CommandSet query, Expression> updator) 63 | { 64 | var sqlProvider = query.SqlProvider; 65 | var dbCon = query.DbCon; 66 | var dbTransaction = query.DbTransaction; 67 | sqlProvider.FormatUpdateSelect(updator); 68 | return (await dbCon.QueryAsync(sqlProvider.SqlString, sqlProvider.Params, dbTransaction)).ToList(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/TableValuedParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Reflection; 4 | 5 | #if !NETSTANDARD1_3 6 | namespace Kogel.Dapper.Extension 7 | { 8 | /// 9 | /// Used to pass a DataTable as a TableValuedParameter 10 | /// 11 | internal sealed class TableValuedParameter : SqlMapper.ICustomQueryParameter 12 | { 13 | private readonly DataTable table; 14 | private readonly string typeName; 15 | 16 | /// 17 | /// Create a new instance of . 18 | /// 19 | /// The to create this parameter for 20 | public TableValuedParameter(DataTable table) : this(table, null) { /* run base */ } 21 | 22 | /// 23 | /// Create a new instance of . 24 | /// 25 | /// The to create this parameter for. 26 | /// The name of the type this parameter is for. 27 | public TableValuedParameter(DataTable table, string typeName) 28 | { 29 | this.table = table; 30 | this.typeName = typeName; 31 | } 32 | 33 | private static readonly Action setTypeName; 34 | static TableValuedParameter() 35 | { 36 | var prop = typeof(System.Data.SqlClient.SqlParameter).GetProperty("TypeName", BindingFlags.Instance | BindingFlags.Public); 37 | if (prop != null && prop.PropertyType == typeof(string) && prop.CanWrite) 38 | { 39 | setTypeName = (Action) 40 | Delegate.CreateDelegate(typeof(Action), prop.GetSetMethod()); 41 | } 42 | } 43 | 44 | void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name) 45 | { 46 | var param = command.CreateParameter(); 47 | param.ParameterName = name; 48 | Set(param, table, typeName); 49 | command.Parameters.Add(param); 50 | } 51 | 52 | internal static void Set(IDbDataParameter parameter, DataTable table, string typeName) 53 | { 54 | #pragma warning disable 0618 55 | parameter.Value = SqlMapper.SanitizeParameterValue(table); 56 | #pragma warning restore 0618 57 | if (string.IsNullOrEmpty(typeName) && table != null) 58 | { 59 | typeName = table.GetTypeName(); 60 | } 61 | if (!string.IsNullOrEmpty(typeName) && (parameter is System.Data.SqlClient.SqlParameter sqlParam)) 62 | { 63 | setTypeName?.Invoke(sqlParam, typeName); 64 | sqlParam.SqlDbType = SqlDbType.Structured; 65 | } 66 | } 67 | } 68 | } 69 | #endif -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Entites/JoinAssTable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text; 5 | using Kogel.Dapper.Extension; 6 | 7 | namespace Kogel.Dapper.Extension.Entites 8 | { 9 | public class JoinAssTable : ICloneable 10 | { 11 | public JoinAssTable() 12 | { 13 | MapperList = new Dictionary(); 14 | } 15 | 16 | public JoinAction Action { get; set; } 17 | public JoinMode JoinMode { get; set; } 18 | public string RightTabName { get; set; } 19 | public string LeftTabName { get; set; } 20 | public string RightAssName { get; set; } 21 | public string LeftAssName { get; set; } 22 | public Type TableType { get; set; } 23 | public string JoinSql { get; set; } 24 | public Type PropertyType { get => PropertyInfo.PropertyType; } 25 | /// 26 | /// 接收导航属性的对象 27 | /// 28 | public PropertyInfo PropertyInfo { get; set; } 29 | 30 | /// 31 | /// 自定义查询的字段 32 | /// 33 | public Dictionary SelectFieldPairs { get; set; } 34 | 35 | /// 36 | /// 表首字段 37 | /// 38 | public string FirstFieldName => MapperList.Values?.AsList()[0]; 39 | 40 | /// 41 | /// 表尾字段 42 | /// 43 | public string LastFieldName => MapperList.Values.AsList()[MapperList.Count - 1]; 44 | 45 | /// 46 | /// 隐射目录 47 | /// 48 | public Dictionary MapperList { get; set; } 49 | 50 | /// 51 | /// 是否手动开关映射(优先级最高) 52 | /// 53 | public bool IsUseMapper { get; set; } = true; 54 | 55 | /// 56 | /// 是否需要隐射字段 57 | /// 58 | public bool IsMapperField { get; set; } = true; 59 | 60 | /// 61 | /// 是否是Dto 62 | /// 63 | public bool IsDto { get; set; } = false; 64 | 65 | /// 66 | /// Dto类 67 | /// 68 | public Type DtoType { get; set; } 69 | 70 | /// 71 | /// 克隆 72 | /// 73 | /// 74 | public object Clone() 75 | { 76 | return new JoinAssTable 77 | { 78 | Action = this.Action, 79 | JoinMode = this.JoinMode, 80 | RightTabName = this.RightTabName, 81 | LeftTabName = this.LeftTabName, 82 | RightAssName = this.RightAssName, 83 | LeftAssName = this.LeftAssName, 84 | TableType = this.TableType, 85 | JoinSql = this.JoinSql, 86 | SelectFieldPairs = new Dictionary(), 87 | MapperList = new Dictionary(), 88 | IsMapperField = false, 89 | PropertyInfo = this.PropertyInfo 90 | }; 91 | } 92 | } 93 | 94 | /// 95 | /// 连表方式 96 | /// 97 | public enum JoinAction 98 | { 99 | Default,//默认表达式 100 | Sql,//sql查询 101 | Navigation//导航属性 102 | } 103 | 104 | public enum JoinMode 105 | { 106 | LEFT,//左连接 107 | RIGHT,//右连接 108 | INNER,//内连接 109 | FULL,//全连接 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Core.Test/FlowOrder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Kogel.Dapper.Extension; 3 | using Kogel.Dapper.Extension.Attributes; 4 | 5 | namespace Core.Test.Model 6 | { 7 | [Display(Rename = "flow_order",AsName = "flow_order1")] 8 | public class FlowOrder : IBaseEntity 9 | { 10 | /// 11 | /// id 12 | /// 13 | [Identity(IsIncrease = true)] 14 | [Display(Rename = "id")] 15 | public override int Id { get; set; } 16 | 17 | /// 18 | /// 业务单号 19 | /// 20 | [Display(Rename = "order_number")] 21 | public string OrderNumber { get; set; } 22 | 23 | /// 24 | /// 参考号 25 | /// 26 | [Display(Rename = "reference_number")] 27 | public string ReferenceNumber { get; set; } 28 | 29 | /// 30 | /// 业务类型 31 | /// 32 | [Display(Rename = "business_type")] 33 | public string BusinessType { get; set; } 34 | 35 | /// 36 | /// 客户代码 37 | /// 38 | [Display(Rename = "customer_code")] 39 | public string CustomerCode { get; set; } 40 | 41 | /// 42 | /// 账户编码 43 | /// 44 | [Display(Rename = "account_code")] 45 | public string AccountCode { get; set; } 46 | 47 | /// 48 | /// 单据时间 49 | /// 50 | [Display(Rename = "order_create_time")] 51 | public DateTime? OrderCreateTime { get; set; } 52 | 53 | /// 54 | /// 来源 55 | /// 56 | [Display(Rename = "source")] 57 | public int Source { get; set; } 58 | 59 | /// 60 | /// 创建时间 61 | /// 62 | [Display(Rename = "create_time")] 63 | public DateTime CreateTime { get; set; } 64 | 65 | /// 66 | /// 更新时间 67 | /// 68 | [Display(Rename = "update_time")] 69 | public DateTime? UpdateTime { get; set; } 70 | 71 | /// 72 | /// 妥投状态 73 | /// 74 | [Display(Rename = "delivered_status")] 75 | public short DeliveredStatus { get; set; } = 1; 76 | 77 | /// 78 | /// 妥投时间 79 | /// 80 | [Display(Rename = "delivered_time")] 81 | public DateTime? DeliveredTime { get; set; } 82 | 83 | /// 84 | /// 妥投接收时间 85 | /// 86 | [Display(Rename = "delivered_receive_time")] 87 | public DateTime? DeliveredReceiveTime { get; set; } 88 | } 89 | 90 | [Display(Rename = "flow_order")] 91 | public class FlowOrder1 : FlowOrder 92 | { 93 | 94 | } 95 | 96 | [Display(Rename = "flow_order")] 97 | public class FlowOrder2 : FlowOrder 98 | { 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/FlowOrder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Kogel.Dapper.Extension.Attributes; 3 | 4 | namespace Kogel.Dapper.Extension.Test.Model 5 | { 6 | [Display(Rename = "flow_order",AsName = "flow_order1")] 7 | public class FlowOrder : IBaseEntity 8 | { 9 | /// 10 | /// id 11 | /// 12 | [Identity(IsIncrease = true)] 13 | [Display(Rename = "id")] 14 | public override long Id { get; set; } 15 | 16 | /// 17 | /// 业务单号 18 | /// 19 | [Display(Rename = "order_number")] 20 | public string OrderNumber { get; set; } 21 | 22 | /// 23 | /// 参考号 24 | /// 25 | [Display(Rename = "reference_number")] 26 | public string ReferenceNumber { get; set; } 27 | 28 | /// 29 | /// 业务类型 30 | /// 31 | [Display(Rename = "business_type")] 32 | public string BusinessType { get; set; } 33 | 34 | /// 35 | /// 客户代码 36 | /// 37 | [Display(Rename = "customer_code")] 38 | public string CustomerCode { get; set; } 39 | 40 | /// 41 | /// 账户编码 42 | /// 43 | [Display(Rename = "account_code")] 44 | public string AccountCode { get; set; } 45 | 46 | /// 47 | /// 单据时间 48 | /// 49 | [Display(Rename = "order_create_time")] 50 | public DateTime? OrderCreateTime { get; set; } 51 | 52 | /// 53 | /// 来源 54 | /// 55 | [Display(Rename = "source")] 56 | public int Source { get; set; } 57 | 58 | /// 59 | /// 创建时间 60 | /// 61 | [Display(Rename = "create_time")] 62 | public DateTime CreateTime { get; set; } 63 | 64 | /// 65 | /// 更新时间 66 | /// 67 | [Display(Rename = "update_time")] 68 | public DateTime? UpdateTime { get; set; } 69 | 70 | /// 71 | /// 妥投状态 72 | /// 73 | [Display(Rename = "delivered_status")] 74 | public short DeliveredStatus { get; set; } = 1; 75 | 76 | /// 77 | /// 妥投时间 78 | /// 79 | [Display(Rename = "delivered_time")] 80 | public DateTime? DeliveredTime { get; set; } 81 | 82 | /// 83 | /// 妥投接收时间 84 | /// 85 | [Display(Rename = "delivered_receive_time")] 86 | public DateTime? DeliveredReceiveTime { get; set; } 87 | } 88 | 89 | [Display(Rename = "flow_order")] 90 | public class FlowOrder1 : FlowOrder 91 | { 92 | 93 | } 94 | 95 | [Display(Rename = "flow_order")] 96 | public class FlowOrder2 : FlowOrder 97 | { 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 54 | 55 | 69 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/UnitTest/Oracle/Command.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Oracle; 2 | using Kogel.Dapper.Extension.Test.Model; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using Oracle.ManagedDataAccess.Client; 7 | using System.Diagnostics; 8 | using System.Linq; 9 | 10 | namespace Kogel.Dapper.Extension.Test.UnitTest.Oracle 11 | { 12 | public class Command 13 | { 14 | 15 | public void Test() 16 | { 17 | using (var conn = new OracleConnection("user id=adonis;password=adonis;data source=192.168.0.120:1521/helowin; Pooling=false;")) 18 | { 19 | 20 | var flowOrder = new FlowOrder 21 | { 22 | AccountCode = "test", 23 | BusinessType = "so", 24 | OrderNumber = Guid.NewGuid().ToString(), 25 | CreateTime = DateTime.Now, 26 | CustomerCode = "test", 27 | DeliveredReceiveTime = DateTime.Now, 28 | DeliveredStatus = 1, 29 | DeliveredTime = DateTime.Now, 30 | OrderCreateTime = DateTime.Now, 31 | ReferenceNumber = "testref", 32 | Source = 1, 33 | UpdateTime = DateTime.Now 34 | }; 35 | var result = conn.CommandSet().Insert(flowOrder); 36 | 37 | 38 | //批量插入 39 | BatchInsert(conn); 40 | } 41 | 42 | } 43 | 44 | //测试批量插入10w条数据 45 | private void BatchInsert(IDbConnection conn) 46 | { 47 | var flowOrders = new FlowOrder 48 | { 49 | AccountCode = "test", 50 | BusinessType = "so", 51 | CreateTime = DateTime.Now, 52 | CustomerCode = "test", 53 | DeliveredReceiveTime = DateTime.Now, 54 | DeliveredStatus = 1, 55 | DeliveredTime = DateTime.Now, 56 | OrderCreateTime = DateTime.Now, 57 | ReferenceNumber = "testref", 58 | Source = 1, 59 | UpdateTime = DateTime.Now 60 | }; 61 | 62 | int total = 10000; 63 | List flows = new List(); 64 | for (var i = 0; i < total; i++) 65 | { 66 | flowOrders.OrderNumber = $"{Guid.NewGuid()}_{i + 1}"; 67 | flows.Add(flowOrders); 68 | } 69 | 70 | int pageSize = 500; 71 | Stopwatch stopwatch = new Stopwatch(); 72 | stopwatch.Start(); 73 | //分100次插入 74 | for (var i = 0; i < total / pageSize; i++) 75 | { 76 | Console.WriteLine(i + 1); 77 | var data = flows.Skip(i * pageSize).Take(pageSize); 78 | conn.CommandSet() 79 | .Insert(data); 80 | } 81 | stopwatch.Stop(); 82 | 83 | Console.WriteLine(stopwatch.Elapsed.TotalSeconds); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Core.Test/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.HttpsPolicy; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Logging; 8 | using Microsoft.Extensions.Options; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Threading.Tasks; 13 | using Kogel.Repository; 14 | using MySql.Data.MySqlClient; 15 | using Kogel.Dapper.Extension.MySql; 16 | using Kogel.Dapper.Extension; 17 | using Core.Test.Model; 18 | using System.Data.SqlClient; 19 | 20 | namespace Core.Test 21 | { 22 | public class Startup 23 | { 24 | public Startup(IConfiguration configuration) 25 | { 26 | Configuration = configuration; 27 | } 28 | 29 | public IConfiguration Configuration { get; } 30 | 31 | // This method gets called by the runtime. Use this method to add services to the container. 32 | public void ConfigureServices(IServiceCollection services) 33 | { 34 | //简便版仓储定义 35 | services.AddKogelRepository((kogel) => 36 | { 37 | //kogel.BuildConnection(x => new MySqlConnection(@"server=192.168.0.120;port=3306;user id=root;password=123456;database=gc_fps_receivable;Persist Security Info=True;")); 38 | //kogel.BuildProvider(x => new MySqlProvider()); 39 | kogel.BuildConnection(x => new SqlConnection("server=192.168.3.9;uid=sa;pwd=ABCabc123;database=XiaoMingMall;"), "master"); 40 | kogel.BuildConnection(x => new SqlConnection("server=192.168.3.9;uid=sa;pwd=ABCabc123;database=KPcba;"), "KPcba"); 41 | kogel.BuildProvider(x => new MsSqlProvider()); 42 | }); 43 | 44 | ////多种不同类型数据库版仓储定义 45 | //services.AddTransient(typeof(IMySqlRepository<>), typeof(MySqlRepository<>)); 46 | 47 | 48 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 49 | } 50 | 51 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 52 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 53 | { 54 | if (env.IsDevelopment()) 55 | { 56 | app.UseDeveloperExceptionPage(); 57 | } 58 | else 59 | { 60 | app.UseHsts(); 61 | } 62 | 63 | app.UseHttpsRedirection(); 64 | app.UseMvc(); 65 | } 66 | } 67 | 68 | 69 | public class MySqlRepository : BaseRepository, IMySqlRepository 70 | { 71 | public override void OnConfiguring(RepositoryOptionsBuilder builder) 72 | { 73 | builder.BuildConnection(x => new MySqlConnection(@"server=192.168.0.120;port=3306;user id=root;password=123456;database=gc_fps_receivable;Persist Security Info=True;")); 74 | builder.BuildProvider(new MySqlProvider()); 75 | } 76 | } 77 | 78 | 79 | public interface IMySqlRepository : IRepository 80 | { 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/DbString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | /// 7 | /// This class represents a SQL string, it can be used if you need to denote your parameter is a Char vs VarChar vs nVarChar vs nChar 8 | /// 9 | public sealed class DbString : SqlMapper.ICustomQueryParameter 10 | { 11 | /// 12 | /// Default value for IsAnsi. 13 | /// 14 | public static bool IsAnsiDefault { get; set; } 15 | 16 | /// 17 | /// A value to set the default value of strings 18 | /// going through Dapper. Default is 4000, any value larger than this 19 | /// field will not have the default value applied. 20 | /// 21 | public const int DefaultLength = 4000; 22 | 23 | /// 24 | /// Create a new DbString 25 | /// 26 | public DbString() 27 | { 28 | Length = -1; 29 | IsAnsi = IsAnsiDefault; 30 | } 31 | /// 32 | /// Ansi vs Unicode 33 | /// 34 | public bool IsAnsi { get; set; } 35 | /// 36 | /// Fixed length 37 | /// 38 | public bool IsFixedLength { get; set; } 39 | /// 40 | /// Length of the string -1 for max 41 | /// 42 | public int Length { get; set; } 43 | /// 44 | /// The value of the string 45 | /// 46 | public string Value { get; set; } 47 | /// 48 | /// Add the parameter to the command... internal use only 49 | /// 50 | /// 51 | /// 52 | public void AddParameter(IDbCommand command, string name) 53 | { 54 | if (IsFixedLength && Length == -1) 55 | { 56 | throw new InvalidOperationException("If specifying IsFixedLength, a Length must also be specified"); 57 | } 58 | bool add = !command.Parameters.Contains(name); 59 | IDbDataParameter param; 60 | if (add) 61 | { 62 | param = command.CreateParameter(); 63 | param.ParameterName = name; 64 | } 65 | else 66 | { 67 | param = (IDbDataParameter)command.Parameters[name]; 68 | } 69 | #pragma warning disable 0618 70 | param.Value = SqlMapper.SanitizeParameterValue(Value); 71 | #pragma warning restore 0618 72 | if (Length == -1 && Value != null && Value.Length <= DefaultLength) 73 | { 74 | param.Size = DefaultLength; 75 | } 76 | else 77 | { 78 | param.Size = Length; 79 | } 80 | param.DbType = IsAnsi ? (IsFixedLength ? DbType.AnsiStringFixedLength : DbType.AnsiString) : (IsFixedLength ? DbType.StringFixedLength : DbType.String); 81 | if (add) 82 | { 83 | command.Parameters.Add(param); 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Expressions/UpdateExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Linq.Expressions; 3 | using System.Text; 4 | using Kogel.Dapper.Extension; 5 | using Kogel.Dapper.Extension.Entites; 6 | using Kogel.Dapper.Extension.Core.Interfaces; 7 | using Kogel.Dapper.Extension; 8 | using Kogel.Dapper.Extension.Extension; 9 | using System; 10 | 11 | namespace Kogel.Dapper.Extension.Expressions 12 | { 13 | public sealed class UpdateExpression : BaseExpressionVisitor 14 | { 15 | #region sql指令 16 | private readonly StringBuilder _sqlCmd; 17 | /// 18 | /// sql指令 19 | /// 20 | public string SqlCmd => _sqlCmd.ToString(); 21 | 22 | public new DynamicParameters Param; 23 | #endregion 24 | /// 25 | /// 26 | /// 执行解析 27 | /// 28 | /// 29 | /// 30 | public UpdateExpression(LambdaExpression expression, SqlProvider provider) : base(provider) 31 | { 32 | this._sqlCmd = new StringBuilder(100); 33 | this.Param = new DynamicParameters(); 34 | //update不需要重命名 35 | providerOption.IsAsName = false; 36 | if (expression.Body is MemberInitExpression) 37 | { 38 | var memberInitExpression = expression.Body as MemberInitExpression; 39 | foreach (MemberAssignment memberInit in memberInitExpression.Bindings) 40 | { 41 | base.SpliceField.Clear(); 42 | base.Param = new DynamicParameters(); 43 | if (_sqlCmd.Length != 0) 44 | _sqlCmd.Append(","); 45 | //实体类型 46 | Type entityType; 47 | //验证是实体类或者是泛型 48 | if (ExpressionExtension.IsAnyBaseEntity(memberInit.Expression.Type, out entityType)) 49 | { 50 | //throw new DapperExtensionException("更新操作不支持导航属性写入"); 51 | #if DEBUG 52 | Console.WriteLine("警告:更新操作不支持导航属性写入!"); 53 | #endif 54 | } 55 | else 56 | { 57 | //值对象 58 | Visit(memberInit.Expression); 59 | var entityObject = EntityCache.QueryEntity(expression.ReturnType); 60 | string fieldName = entityObject.FieldPairs[memberInit.Member.Name]; 61 | _sqlCmd.Append($" {provider.ProviderOption.CombineFieldName(fieldName)} = {base.SpliceField} "); 62 | Param.AddDynamicParams(base.Param); 63 | } 64 | base.Index++; 65 | } 66 | _sqlCmd.Insert(0, " SET "); 67 | } 68 | else//匿名类 69 | { 70 | var entityValue = expression.Body.ToConvertAndGetValue(); 71 | string sql = provider.ResolveExpression.ResolveUpdate((T)entityValue, Param, null); 72 | _sqlCmd.Append(sql); 73 | //throw new DapperExtensionException("更新操作不支持匿名类写入"); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Collections.Generic; 4 | 5 | namespace Kogel.Dapper.Extension 6 | { 7 | internal static class TypeExtensions 8 | { 9 | public static string Name(this Type type) => 10 | #if NETSTANDARD1_3 || NETCOREAPP1_0 11 | type.GetTypeInfo().Name; 12 | #else 13 | type.Name; 14 | #endif 15 | 16 | public static bool IsValueType(this Type type) => 17 | #if NETSTANDARD1_3 || NETCOREAPP1_0 18 | type.GetTypeInfo().IsValueType; 19 | #else 20 | type.IsValueType; 21 | #endif 22 | 23 | public static bool IsEnum(this Type type) => 24 | #if NETSTANDARD1_3 || NETCOREAPP1_0 25 | type.GetTypeInfo().IsEnum; 26 | #else 27 | type.IsEnum; 28 | #endif 29 | 30 | public static bool IsGenericType(this Type type) => 31 | #if NETSTANDARD1_3 || NETCOREAPP1_0 32 | type.GetTypeInfo().IsGenericType; 33 | #else 34 | type.IsGenericType; 35 | #endif 36 | 37 | public static bool IsInterface(this Type type) => 38 | #if NETSTANDARD1_3 || NETCOREAPP1_0 39 | type.GetTypeInfo().IsInterface; 40 | #else 41 | type.IsInterface; 42 | #endif 43 | 44 | #if NETSTANDARD1_3 || NETCOREAPP1_0 45 | public static IEnumerable GetCustomAttributes(this Type type, bool inherit) 46 | { 47 | return type.GetTypeInfo().GetCustomAttributes(inherit); 48 | } 49 | 50 | public static TypeCode GetTypeCode(Type type) 51 | { 52 | if (type == null) return TypeCode.Empty; 53 | if (typeCodeLookup.TryGetValue(type, out TypeCode result)) return result; 54 | 55 | if (type.IsEnum()) 56 | { 57 | type = Enum.GetUnderlyingType(type); 58 | if (typeCodeLookup.TryGetValue(type, out result)) return result; 59 | } 60 | return TypeCode.Object; 61 | } 62 | 63 | private static readonly Dictionary typeCodeLookup = new Dictionary 64 | { 65 | [typeof(bool)] = TypeCode.Boolean, 66 | [typeof(byte)] = TypeCode.Byte, 67 | [typeof(char)] = TypeCode.Char, 68 | [typeof(DateTime)] = TypeCode.DateTime, 69 | [typeof(decimal)] = TypeCode.Decimal, 70 | [typeof(double)] = TypeCode.Double, 71 | [typeof(short)] = TypeCode.Int16, 72 | [typeof(int)] = TypeCode.Int32, 73 | [typeof(long)] = TypeCode.Int64, 74 | [typeof(object)] = TypeCode.Object, 75 | [typeof(sbyte)] = TypeCode.SByte, 76 | [typeof(float)] = TypeCode.Single, 77 | [typeof(string)] = TypeCode.String, 78 | [typeof(ushort)] = TypeCode.UInt16, 79 | [typeof(uint)] = TypeCode.UInt32, 80 | [typeof(ulong)] = TypeCode.UInt64, 81 | }; 82 | #else 83 | public static TypeCode GetTypeCode(Type type) => Type.GetTypeCode(type); 84 | #endif 85 | 86 | public static MethodInfo GetPublicInstanceMethod(this Type type, string name, Type[] types) 87 | { 88 | #if NETSTANDARD1_3 || NETCOREAPP1_0 89 | var method = type.GetMethod(name, types); 90 | return (method?.IsPublic == true && !method.IsStatic) ? method : null; 91 | #else 92 | return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public, null, types, null); 93 | #endif 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Helper/Cache/EntityCache.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension; 2 | using Kogel.Dapper.Extension.Extension; 3 | using Kogel.Dapper.Extension.Helper; 4 | using Kogel.Dapper.Extension.Entites; 5 | using System; 6 | using System.Collections.Concurrent; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Reflection; 10 | using System.Text; 11 | 12 | namespace Kogel.Dapper.Extension 13 | { 14 | /// 15 | /// 实体类缓存 16 | /// 17 | public class EntityCache 18 | { 19 | internal static ConcurrentBag EntitieList = new ConcurrentBag(); 20 | /// 21 | /// 注册动态化查询可能会用到的实体类 22 | /// 23 | /// 实体类 24 | public static EntityObject Register(Type entity) 25 | { 26 | EntityObject entityObject = new EntityObject(entity); 27 | if (!EntitieList.Any(x => x.AssemblyString.Equals(entityObject.AssemblyString))) 28 | { 29 | SqlMapper.SetTypeMap(entityObject.Type, new CustomPropertyTypeMap(entityObject.Type, 30 | (type, column) => 31 | type.GetPropertys(entityObject.FieldPairs.FirstOrDefault(x => x.Value.Equals(column)).Key) 32 | )); 33 | EntitieList.Add(entityObject); 34 | } 35 | return entityObject; 36 | } 37 | 38 | /// 39 | /// 注册动态化查询可能会用到的实体类 40 | /// 41 | /// 实体类 42 | public static void Register(Type[] entitys) 43 | { 44 | foreach (var item in entitys) 45 | { 46 | Register(item); 47 | } 48 | } 49 | 50 | /// 51 | /// 注册动态化查询可能会用到的实体类 52 | /// 53 | /// 通过给定程序集的长格式名称加载程序集。 54 | public static void Register(string assemblyString) 55 | { 56 | Assembly assembly = Assembly.Load(assemblyString); 57 | Register(assembly.GetTypes()); 58 | } 59 | 60 | /// 61 | /// 查询实体类信息 62 | /// 63 | /// 64 | /// 65 | public static EntityObject QueryEntity(Type entity) 66 | { 67 | var entityType = EntitieList.FirstOrDefault(x => x.Type.FullName?.Equals(entity.FullName) == true); 68 | if (entityType != null) 69 | { 70 | return entityType; 71 | } 72 | else 73 | { 74 | return Register(entity); 75 | } 76 | } 77 | 78 | /// 79 | /// 查询实体类信息(模糊查询) 80 | /// 81 | /// 82 | /// 83 | public static EntityObject QueryEntity(string entityFullName) 84 | { 85 | var entityType = EntitieList.FirstOrDefault(x => x.Type.FullName.Contains(entityFullName)); 86 | return entityType; 87 | } 88 | 89 | /// 90 | /// 获取所有实体 91 | /// 92 | /// 93 | public static List GetEntities() 94 | { 95 | return EntitieList.Where(x => ExpressionExtension.IsAnyBaseEntity(x.Type, out Type entityType)).Distinct().ToList(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.TypeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | /// 9 | /// Base-class for simple type-handlers 10 | /// 11 | /// This this handler is for. 12 | public abstract class TypeHandler : ITypeHandler 13 | { 14 | /// 15 | /// Assign the value of a parameter before a command executes 16 | /// 17 | /// The parameter to configure 18 | /// Parameter value 19 | public abstract void SetValue(IDbDataParameter parameter, T value); 20 | 21 | /// 22 | /// Parse a database value back to a typed value 23 | /// 24 | /// The value from the database 25 | /// The typed value 26 | public abstract T Parse(object value); 27 | 28 | void ITypeHandler.SetValue(IDbDataParameter parameter, object value) 29 | { 30 | if (value is DBNull) 31 | { 32 | parameter.Value = value; 33 | } 34 | else 35 | { 36 | SetValue(parameter, (T)value); 37 | } 38 | } 39 | 40 | object ITypeHandler.Parse(Type destinationType, object value) 41 | { 42 | return Parse(value); 43 | } 44 | } 45 | 46 | /// 47 | /// Base-class for simple type-handlers that are based around strings 48 | /// 49 | /// This this handler is for. 50 | public abstract class StringTypeHandler : TypeHandler 51 | { 52 | /// 53 | /// Parse a string into the expected type (the string will never be null) 54 | /// 55 | /// The string to parse. 56 | protected abstract T Parse(string xml); 57 | 58 | /// 59 | /// Format an instace into a string (the instance will never be null) 60 | /// 61 | /// The string to format. 62 | protected abstract string Format(T xml); 63 | 64 | /// 65 | /// Assign the value of a parameter before a command executes 66 | /// 67 | /// The parameter to configure 68 | /// Parameter value 69 | public override void SetValue(IDbDataParameter parameter, T value) 70 | { 71 | parameter.Value = value == null ? (object)DBNull.Value : Format(value); 72 | } 73 | 74 | /// 75 | /// Parse a database value back to a typed value 76 | /// 77 | /// The value from the database 78 | /// The typed value 79 | public override T Parse(object value) 80 | { 81 | if (value == null || value is DBNull) return default(T); 82 | return Parse((string)value); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Helper/VersionCompatible.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Linq; 4 | 5 | namespace Kogel.Dapper.Extension.Helper 6 | { 7 | /// 8 | /// [已弃用]版本兼容类(兼容.netstandard1.3的语法) 9 | /// 10 | public static class VersionCompatible 11 | { 12 | public static Type BaseTypes(this Type PropertyType) 13 | { 14 | #if NETSTANDARD1_3 15 | return PropertyType.GetTypeInfo().BaseType; 16 | #else 17 | return PropertyType.BaseType; 18 | #endif 19 | } 20 | public static bool IsGenericTypes(this Type PropertyType) 21 | { 22 | #if NETSTANDARD1_3 23 | return PropertyType.GetTypeInfo().IsGenericType; 24 | #else 25 | return PropertyType.IsGenericType; 26 | #endif 27 | } 28 | public static bool IsEnums(this Type PropertyType) 29 | { 30 | #if NETSTANDARD1_3 31 | return PropertyType.GetTypeInfo().IsEnum; 32 | #else 33 | return PropertyType.IsEnum; 34 | #endif 35 | } 36 | public static bool IsValueTypes(this Type PropertyType) 37 | { 38 | #if NETSTANDARD1_3 39 | return PropertyType.GetTypeInfo().IsValueType; 40 | #else 41 | return PropertyType.IsValueType; 42 | #endif 43 | } 44 | public static PropertyInfo GetPropertys(this Type PropertyType, string name) 45 | { 46 | #if NETSTANDARD1_3 47 | return PropertyType.GetTypeInfo().GetDeclaredProperty(name); 48 | #else 49 | if (string.IsNullOrEmpty(name)) { return null; } 50 | return PropertyType.GetProperty(name); 51 | #endif 52 | } 53 | public static MethodInfo GetMethodInfos(this Type PropertyType,string name) 54 | { 55 | #if NETSTANDARD1_3 56 | return PropertyType.GetTypeInfo().GetDeclaredMethod(name); 57 | #else 58 | if (string.IsNullOrEmpty(name)) { return null; } 59 | return PropertyType.GetMethod(name); 60 | #endif 61 | } 62 | public static MethodInfo[] GetMethodss(this Type PropertyType) 63 | { 64 | #if NETSTANDARD1_3 65 | return PropertyType.GetTypeInfo().DeclaredMethods.ToArray(); 66 | #else 67 | return PropertyType.GetMethods(); 68 | #endif 69 | } 70 | /// 71 | /// 当在派生类中重写,则返回的所有自定义特性应用于此成员的数组。 72 | /// 73 | /// 74 | /// true 搜索此成员继承链,以查找这些属性;否则为 false。 属性和事件,则忽略此参数请参阅备注。 75 | /// 76 | public static object[] GetCustomAttributess(this Type PropertyType,bool inherit) 77 | { 78 | #if NETSTANDARD1_3 79 | return PropertyType.GetTypeInfo().GetCustomAttributes().ToArray(); 80 | #else 81 | return PropertyType.GetCustomAttributes(inherit); 82 | #endif 83 | } 84 | public static object [] GetCustomAttributess(this PropertyInfo PropertyInfo,bool inherit) 85 | { 86 | #if NETSTANDARD1_3 87 | return PropertyInfo.GetType().GetTypeInfo().GetCustomAttributes().ToArray(); 88 | #else 89 | return PropertyInfo.GetCustomAttributes(inherit); 90 | #endif 91 | } 92 | public static Type ReflectedTypes(this MethodInfo method) 93 | { 94 | #if NETSTANDARD1_3 95 | return method.ReturnType; 96 | #else 97 | return method.ReflectedType; 98 | #endif 99 | } 100 | 101 | public static PropertyInfo[] GetPropertiess(this Type PropertyType) 102 | { 103 | #if NETSTANDARD1_3 104 | return PropertyType.GetProperties(); 105 | #else 106 | return PropertyType.GetProperties(); 107 | #endif 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/SqlMapper.DapperRowMetaObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | namespace Kogel.Dapper.Extension 5 | { 6 | public static partial class SqlMapper 7 | { 8 | private sealed class DapperRowMetaObject : System.Dynamic.DynamicMetaObject 9 | { 10 | private static readonly MethodInfo getValueMethod = typeof(IDictionary).GetProperty("Item").GetGetMethod(); 11 | private static readonly MethodInfo setValueMethod = typeof(DapperRow).GetMethod("SetValue", new Type[] { typeof(string), typeof(object) }); 12 | 13 | public DapperRowMetaObject( 14 | System.Linq.Expressions.Expression expression, 15 | System.Dynamic.BindingRestrictions restrictions 16 | ) 17 | : base(expression, restrictions) 18 | { 19 | } 20 | 21 | public DapperRowMetaObject( 22 | System.Linq.Expressions.Expression expression, 23 | System.Dynamic.BindingRestrictions restrictions, 24 | object value 25 | ) 26 | : base(expression, restrictions, value) 27 | { 28 | } 29 | 30 | private System.Dynamic.DynamicMetaObject CallMethod( 31 | MethodInfo method, 32 | System.Linq.Expressions.Expression[] parameters 33 | ) 34 | { 35 | var callMethod = new System.Dynamic.DynamicMetaObject( 36 | System.Linq.Expressions.Expression.Call( 37 | System.Linq.Expressions.Expression.Convert(Expression, LimitType), 38 | method, 39 | parameters), 40 | System.Dynamic.BindingRestrictions.GetTypeRestriction(Expression, LimitType) 41 | ); 42 | return callMethod; 43 | } 44 | 45 | public override System.Dynamic.DynamicMetaObject BindGetMember(System.Dynamic.GetMemberBinder binder) 46 | { 47 | var parameters = new System.Linq.Expressions.Expression[] 48 | { 49 | System.Linq.Expressions.Expression.Constant(binder.Name) 50 | }; 51 | 52 | var callMethod = CallMethod(getValueMethod, parameters); 53 | 54 | return callMethod; 55 | } 56 | 57 | // Needed for Visual basic dynamic support 58 | public override System.Dynamic.DynamicMetaObject BindInvokeMember(System.Dynamic.InvokeMemberBinder binder, System.Dynamic.DynamicMetaObject[] args) 59 | { 60 | var parameters = new System.Linq.Expressions.Expression[] 61 | { 62 | System.Linq.Expressions.Expression.Constant(binder.Name) 63 | }; 64 | 65 | var callMethod = CallMethod(getValueMethod, parameters); 66 | 67 | return callMethod; 68 | } 69 | 70 | public override System.Dynamic.DynamicMetaObject BindSetMember(System.Dynamic.SetMemberBinder binder, System.Dynamic.DynamicMetaObject value) 71 | { 72 | var parameters = new System.Linq.Expressions.Expression[] 73 | { 74 | System.Linq.Expressions.Expression.Constant(binder.Name), 75 | value.Expression, 76 | }; 77 | 78 | var callMethod = CallMethod(setValueMethod, parameters); 79 | 80 | return callMethod; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Core.Test/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using Core.Test.Model; 2 | using Kogel.Repository; 3 | using Microsoft.AspNetCore.Mvc; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using Kogel.Dapper.Extension; 9 | using Kogel.Dapper.Extension.Attributes; 10 | using System.Xml.Linq; 11 | using Kogel.Repository.Interfaces; 12 | using System.Data.SqlClient; 13 | 14 | namespace Core.Test.Controllers 15 | { 16 | [Route("api/[controller]")] 17 | [ApiController] 18 | public class ValuesController : ControllerBase 19 | { 20 | IRepository repository; 21 | 22 | IBaseRepository repository1; 23 | IBaseRepository repository2; 24 | public ValuesController(IRepository repository) 25 | { 26 | this.repository = repository; 27 | //copy第一个仓储对象 28 | this.repository1 = repository.QuerySet().GetRepository(); 29 | //并切换到另一个数据源 30 | this.repository1.ChangeDataBase("master"); 31 | //copy第二个仓储对象 32 | this.repository2 = repository.QuerySet().GetRepository(); 33 | //并切换到另一个数据源 34 | this.repository2.ChangeDataBase("KPcba"); 35 | 36 | 37 | SqlMapper.Aop.OnExecuting += Aop_OnExecuting; 38 | } 39 | 40 | private void Aop_OnExecuting(ref CommandDefinition command) 41 | { 42 | 43 | } 44 | 45 | //// GET api/values 46 | //[HttpGet] 47 | //public ActionResult Get() 48 | //{ 49 | // var flowOrder = repository.QuerySet() 50 | // .Top(100) 51 | // .Distinct() 52 | // .ToList(x => new 53 | // { 54 | // x.CustomerCode 55 | // }); 56 | // return flowOrder; 57 | //} 58 | 59 | [HttpGet] 60 | public ActionResult TestUnitOfWork() 61 | { 62 | //测试不同数据库中多阶段事务提交 63 | repository1.UnitOfWork.BeginTransaction(XaBeginMethod); 64 | //这里会做统一提交 65 | repository1.UnitOfWork.Rollback(); 66 | return "success"; 67 | } 68 | 69 | public void XaBeginMethod() 70 | { 71 | _ = repository1.CommandSet() 72 | .Where(x => x.Name == "1") 73 | .Update(x => new Test 74 | { 75 | Name = Function.IfNull(x.Name, "123") + "4" 76 | }); 77 | 78 | repository1.Insert(new Test { Name = "1" }); 79 | repository2.Insert(new Test { Name = "2" }); 80 | 81 | repository2.UnitOfWork.BeginTransaction(() => 82 | { 83 | repository2.Insert(new Test { Name = "3" }); 84 | }); 85 | //因为嵌套工作单元和不是一个db连接的关系,这里是一个伪提交 86 | repository2.UnitOfWork.Commit(); 87 | 88 | //甚至写sql都可以哦,一样会强制进入到事务中 89 | using (var conn = new SqlConnection("server=192.168.3.9;uid=sa;pwd=ABCabc123;database=XiaoMingMall;")) 90 | { 91 | var id = conn.ExecuteScalar("Insert into test(name)values('kogel牛逼!')SELECT @@IDENTITY"); 92 | } 93 | } 94 | 95 | } 96 | 97 | 98 | /// 99 | /// 100 | /// 101 | [Display(Rename = "test")] 102 | public class Test 103 | { 104 | /// 105 | /// 106 | /// 107 | [Identity] 108 | [Display(Rename = "id")] 109 | public int Id { get; set; } 110 | 111 | /// 112 | /// 113 | /// 114 | [Display(Rename = "name")] 115 | public string Name { get; set; } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Dapper/WrappedReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | 4 | namespace Kogel.Dapper.Extension 5 | { 6 | internal class WrappedReader : IWrappedDataReader 7 | { 8 | private IDataReader reader; 9 | private IDbCommand cmd; 10 | 11 | public IDataReader Reader 12 | { 13 | get 14 | { 15 | var tmp = reader; 16 | if (tmp == null) throw new ObjectDisposedException(GetType().Name); 17 | return tmp; 18 | } 19 | } 20 | 21 | IDbCommand IWrappedDataReader.Command 22 | { 23 | get 24 | { 25 | var tmp = cmd; 26 | if (tmp == null) throw new ObjectDisposedException(GetType().Name); 27 | return tmp; 28 | } 29 | } 30 | 31 | public WrappedReader(IDbCommand cmd, IDataReader reader) 32 | { 33 | this.cmd = cmd; 34 | this.reader = reader; 35 | } 36 | 37 | void IDataReader.Close() => reader?.Close(); 38 | 39 | int IDataReader.Depth => Reader.Depth; 40 | 41 | DataTable IDataReader.GetSchemaTable() => Reader.GetSchemaTable(); 42 | 43 | bool IDataReader.IsClosed => reader?.IsClosed ?? true; 44 | 45 | bool IDataReader.NextResult() => Reader.NextResult(); 46 | 47 | bool IDataReader.Read() => Reader.Read(); 48 | 49 | int IDataReader.RecordsAffected => Reader.RecordsAffected; 50 | 51 | void IDisposable.Dispose() 52 | { 53 | reader?.Close(); 54 | reader?.Dispose(); 55 | reader = null; 56 | cmd?.Dispose(); 57 | cmd = null; 58 | } 59 | 60 | int IDataRecord.FieldCount => Reader.FieldCount; 61 | 62 | bool IDataRecord.GetBoolean(int i) => Reader.GetBoolean(i); 63 | 64 | byte IDataRecord.GetByte(int i) => Reader.GetByte(i); 65 | 66 | long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) => 67 | Reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length); 68 | 69 | char IDataRecord.GetChar(int i) => Reader.GetChar(i); 70 | 71 | long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) => 72 | Reader.GetChars(i, fieldoffset, buffer, bufferoffset, length); 73 | 74 | IDataReader IDataRecord.GetData(int i) => Reader.GetData(i); 75 | 76 | string IDataRecord.GetDataTypeName(int i) => Reader.GetDataTypeName(i); 77 | 78 | DateTime IDataRecord.GetDateTime(int i) => Reader.GetDateTime(i); 79 | 80 | decimal IDataRecord.GetDecimal(int i) => Reader.GetDecimal(i); 81 | 82 | double IDataRecord.GetDouble(int i) => Reader.GetDouble(i); 83 | 84 | Type IDataRecord.GetFieldType(int i) => Reader.GetFieldType(i); 85 | 86 | float IDataRecord.GetFloat(int i) => Reader.GetFloat(i); 87 | 88 | Guid IDataRecord.GetGuid(int i) => Reader.GetGuid(i); 89 | 90 | short IDataRecord.GetInt16(int i) => Reader.GetInt16(i); 91 | 92 | int IDataRecord.GetInt32(int i) => Reader.GetInt32(i); 93 | 94 | long IDataRecord.GetInt64(int i) => Reader.GetInt64(i); 95 | 96 | string IDataRecord.GetName(int i) => Reader.GetName(i); 97 | 98 | int IDataRecord.GetOrdinal(string name) => Reader.GetOrdinal(name); 99 | 100 | string IDataRecord.GetString(int i) => Reader.GetString(i); 101 | 102 | object IDataRecord.GetValue(int i) => Reader.GetValue(i); 103 | 104 | int IDataRecord.GetValues(object[] values) => Reader.GetValues(values); 105 | 106 | bool IDataRecord.IsDBNull(int i) => Reader.IsDBNull(i); 107 | 108 | object IDataRecord.this[string name] => Reader[name]; 109 | 110 | object IDataRecord.this[int i] => Reader[i]; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension.Test/Model/HeadOrder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Kogel.Dapper.Extension.Attributes; 7 | 8 | namespace Kogel.Dapper.Extension.Test.Model 9 | { 10 | public class HeadOrder : IBaseEntity 11 | { 12 | /// 13 | /// 14 | /// 15 | [Identity] 16 | [Display(Rename = "HeadOrderId")] 17 | public override int Id { get; set; } 18 | /// 19 | /// 20 | /// 21 | public string OrderNumber { get; set; } 22 | /// 23 | /// 24 | /// 25 | public string TransportOrderNumber { get; set; } 26 | /// 27 | /// 28 | /// 29 | public string ReferenceNumber { get; set; } 30 | /// 31 | /// 32 | /// 33 | public string AccountCode { get; set; } 34 | /// 35 | /// 36 | /// 37 | public string CustomerCode { get; set; } 38 | /// 39 | /// 40 | /// 41 | public int BusinessType { get; set; } 42 | /// 43 | /// 44 | /// 45 | public string TransportMode { get; set; } 46 | /// 47 | /// 48 | /// 49 | public string LogisticsProductsCode { get; set; } 50 | /// 51 | /// FPS-快递 52 | /// 53 | public string LogisticsProductsName { get; set; } 54 | /// 55 | /// 56 | /// 57 | public string DestinationCountry { get; set; } 58 | /// 59 | /// 60 | /// 61 | public int UnitPrice { get; set; } 62 | /// 63 | /// 64 | /// 65 | public int CBM { get; set; } 66 | /// 67 | /// 68 | /// 69 | public int Carton { get; set; } 70 | /// 71 | /// 72 | /// 73 | public int Weight { get; set; } 74 | /// 75 | /// 76 | /// 77 | public string ETD { get; set; } 78 | /// 79 | /// 80 | /// 81 | public string ETA { get; set; } 82 | /// 83 | /// 84 | /// 85 | public string OrderAddTime { get; set; } 86 | /// 87 | /// 88 | /// 89 | public string ExportTime { get; set; } 90 | /// 91 | /// 92 | /// 93 | public string AddTime { get; set; } 94 | /// 95 | /// 96 | /// 97 | public string UpdateTime { get; set; } 98 | /// 99 | /// 100 | /// 101 | public string TargetWarehouseCode { get; set; } 102 | /// 103 | /// 美东仓库 104 | /// 105 | public string TargetWarehouseName { get; set; } 106 | /// 107 | /// 108 | /// 109 | public string TransferWarehouseCode { get; set; } 110 | /// 111 | /// 深圳仓库 112 | /// 113 | public string TransferWarehouseName { get; set; } 114 | /// 115 | /// 空运-KY 116 | /// 117 | public string TransportTypeName { get; set; } 118 | /// 119 | /// 120 | /// 121 | public string CabinetType { get; set; } 122 | /// 123 | /// 124 | /// 125 | public string CustomerAbbreviation { get; set; } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/SetC/CommandSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using Kogel.Dapper.Extension; 7 | using Kogel.Dapper.Extension.Core.Interfaces; 8 | using Kogel.Dapper.Extension.Helper; 9 | using Kogel.Dapper.Extension.Entites; 10 | 11 | namespace Kogel.Dapper.Extension.Core.SetC 12 | { 13 | /// 14 | /// 指令集 15 | /// 16 | /// 17 | public class CommandSet : Command, ICommandSet 18 | { 19 | public CommandSet(IDbConnection conn, SqlProvider sqlProvider) : base(conn, sqlProvider) 20 | { 21 | TableType = typeof(T); 22 | SetContext = new DataBaseContext 23 | { 24 | Set = this, 25 | OperateType = EOperateType.Command 26 | }; 27 | 28 | sqlProvider.Context = SetContext; 29 | sqlProvider.IsAppendAsName = false; 30 | WhereExpressionList = new List(); 31 | WhereBuilder = new StringBuilder(); 32 | Params = new DynamicParameters(); 33 | } 34 | 35 | public CommandSet(IDbConnection conn, SqlProvider sqlProvider, IDbTransaction dbTransaction) : base(conn, sqlProvider, dbTransaction) 36 | { 37 | TableType = typeof(T); 38 | SetContext = new DataBaseContext 39 | { 40 | Set = this, 41 | OperateType = EOperateType.Command 42 | }; 43 | 44 | sqlProvider.Context = SetContext; 45 | sqlProvider.IsAppendAsName = false; 46 | WhereExpressionList = new List(); 47 | WhereBuilder = new StringBuilder(); 48 | Params = new DynamicParameters(); 49 | } 50 | 51 | internal CommandSet(IDbConnection conn, SqlProvider sqlProvider, Type tableType, LambdaExpression whereExpression) : base(conn, sqlProvider) 52 | { 53 | TableType = tableType; 54 | //WhereExpression = whereExpression; 55 | SetContext = new DataBaseContext 56 | { 57 | Set = this, 58 | OperateType = EOperateType.Command 59 | }; 60 | 61 | sqlProvider.Context = SetContext; 62 | sqlProvider.IsAppendAsName = false; 63 | WhereExpressionList = new List(); 64 | WhereExpressionList.Add(whereExpression); 65 | WhereBuilder = new StringBuilder(); 66 | Params = new DynamicParameters(); 67 | } 68 | 69 | public ICommandSet ResetTableName(Type type, string tableName) 70 | { 71 | SqlProvider.AsTableNameDic.Add(type, tableName); 72 | return this; 73 | } 74 | /// 75 | /// 76 | /// 77 | /// 78 | /// 79 | public ICommandSet Where(Expression> predicate) 80 | { 81 | WhereExpressionList.Add(predicate); 82 | return this; 83 | } 84 | /// 85 | /// 使用sql查询条件 86 | /// 87 | /// 88 | /// 89 | /// 90 | public ICommandSet Where(string sqlWhere, object param = null) 91 | { 92 | WhereBuilder.Append(" AND " + sqlWhere); 93 | if (param != null) 94 | { 95 | Params.AddDynamicParams(param); 96 | } 97 | return this; 98 | } 99 | /// 100 | /// 101 | /// 102 | /// 103 | /// 104 | /// 105 | /// 106 | public ICommandSet WhereIf(bool where, Expression> truePredicate, Expression> falsePredicate) 107 | { 108 | if (where) 109 | WhereExpressionList.Add(truePredicate); 110 | else 111 | WhereExpressionList.Add(falsePredicate); 112 | return this; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Kogel.Dapper.Extension/Core/SetQ/QuerySet.Where.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.Interfaces; 2 | using Kogel.Dapper.Extension.Entites; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Kogel.Dapper.Extension.Core.SetQ 11 | { 12 | /// 13 | /// 条件筛选 14 | /// 15 | /// 16 | public partial class QuerySet : Aggregation, IQuerySet 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public IQuerySet Where(Expression> predicate) 24 | { 25 | WhereExpressionList.Add(predicate); 26 | return this; 27 | } 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | public IQuerySet Where(Expression> predicate) 36 | { 37 | WhereExpressionList.Add(predicate); 38 | return this; 39 | } 40 | 41 | /// 42 | /// 动态化查讯(转换成表达式树集合) 注意,int参数不会判断为0的值 43 | /// 44 | /// 45 | /// 46 | public IQuerySet Where(Dictionary dynamicTree) 47 | { 48 | WhereExpressionList.AddRange(SqlProvider.FormatDynamicTreeWhereExpression(dynamicTree)); 49 | return this; 50 | } 51 | 52 | /// 53 | /// 使用sql查询条件 54 | /// 55 | /// 56 | /// 57 | /// 58 | public IQuerySet Where(string sqlWhere, object param = null) 59 | { 60 | WhereBuilder.Append(" AND " + sqlWhere); 61 | if (param != null) 62 | { 63 | Params.AddDynamicParams(param, true); 64 | } 65 | return this; 66 | } 67 | 68 | /// 69 | /// 70 | /// 71 | /// 72 | /// 73 | /// 74 | /// 75 | public IQuerySet Where(Expression> exp) 76 | { 77 | WhereExpressionList.Add(exp); 78 | return this; 79 | } 80 | 81 | /// 82 | /// 带前置条件的Where判断 83 | /// 84 | /// 85 | /// 86 | /// 87 | /// 88 | public IQuerySet WhereIf(bool where, Expression> truePredicate, Expression> falsePredicate) 89 | { 90 | if (where) 91 | WhereExpressionList.Add(truePredicate); 92 | else 93 | WhereExpressionList.Add(falsePredicate); 94 | return this; 95 | } 96 | 97 | /// 98 | /// 带前置条件的Where判断 99 | /// 100 | /// 101 | /// 102 | /// 103 | /// 104 | /// 105 | public IQuerySet WhereIf(bool where, Expression> truePredicate, Expression> falsePredicate) 106 | { 107 | if (where) 108 | WhereExpressionList.Add(truePredicate); 109 | else 110 | WhereExpressionList.Add(falsePredicate); 111 | return this; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Kogel.Repository/Interfaces/IBaseRepository.cs: -------------------------------------------------------------------------------- 1 | using Kogel.Dapper.Extension.Core.SetQ; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Data; 8 | using Kogel.Dapper.Extension.Core.SetC; 9 | using Kogel.Dapper.Extension.Core.Interfaces; 10 | 11 | namespace Kogel.Repository.Interfaces 12 | { 13 | public interface IBaseRepository: IDisposable 14 | { 15 | /// 16 | /// 当前的连接对象 17 | /// 18 | IDbConnection Orm { get; } 19 | 20 | /// 21 | /// 改变当前连接库(分库时可能会用到) 22 | /// 23 | /// 24 | void ChangeDataBase(string dbName = "master"); 25 | 26 | /// 27 | /// 改变当前提供方(分库时可能会用到) 28 | /// 29 | /// 30 | void ChangeProvider(string dbName = "master"); 31 | 32 | /// 33 | /// 工作单元 34 | /// 35 | IUnitOfWork UnitOfWork { get; set; } 36 | 37 | /// 38 | /// 获取查询对象 39 | /// 40 | /// 41 | IQuerySet QuerySet(); 42 | 43 | /// 44 | /// 获取查询对象 45 | /// 46 | /// 47 | /// 48 | IQuerySet QuerySet(IDbTransaction transaction); 49 | 50 | /// 51 | /// 获取查询对象 52 | /// 53 | /// 54 | /// 55 | IQuerySet QuerySet(); 56 | 57 | /// 58 | /// 获取查询对象 59 | /// 60 | /// 61 | /// 62 | /// 63 | IQuerySet QuerySet(IDbTransaction transaction); 64 | 65 | /// 66 | /// 获取编辑对象 67 | /// 68 | /// 69 | ICommandSet CommandSet(); 70 | 71 | /// 72 | /// 获取编辑对象 73 | /// 74 | /// 75 | /// 76 | ICommandSet CommandSet(IDbTransaction transaction); 77 | 78 | /// 79 | /// 获取编辑对象 80 | /// 81 | /// 82 | /// 83 | ICommandSet CommandSet(); 84 | 85 | /// 86 | /// 获取编辑对象 87 | /// 88 | /// 89 | /// 90 | /// 91 | ICommandSet CommandSet(IDbTransaction transaction); 92 | 93 | /// 94 | /// 根据主键获取当前实体数据 95 | /// 96 | /// 97 | /// 98 | T FindById(object id); 99 | 100 | /// 101 | /// 根据主键获取当前实体数据 102 | /// 103 | /// 104 | /// 105 | Task FindByIdAsync(object id); 106 | 107 | /// 108 | /// 新增 109 | /// 110 | /// 111 | /// 112 | int Insert(T entity); 113 | 114 | /// 115 | /// 批量新增 116 | /// 117 | /// 118 | /// 119 | int Insert(IEnumerable entitys); 120 | 121 | /// 122 | /// 新增 123 | /// 124 | /// 125 | /// 126 | Task InsertAsync(T entity); 127 | 128 | /// 129 | /// 批量新增 130 | /// 131 | /// 132 | /// 133 | Task InsertAsync(IEnumerable entitys); 134 | 135 | /// 136 | /// 删除(根据主键) 137 | /// 138 | /// 139 | /// 140 | int Delete(object id); 141 | 142 | /// 143 | /// 删除(根据主键) 144 | /// 145 | /// 146 | /// 147 | Task DeleteAsync(object id); 148 | 149 | /// 150 | /// 修改(根据主键) 151 | /// 152 | /// 153 | /// 154 | int Update(T entity); 155 | 156 | /// 157 | /// 修改(根据主键) 158 | /// 159 | /// 160 | /// 161 | Task UpdateAsync(T entity); 162 | } 163 | } 164 | --------------------------------------------------------------------------------