Support custom SqlFunc Method

This commit is contained in:
sunkaixuan
2017-11-17 14:08:25 +08:00
parent 2dca1b923d
commit d66e84c911
15 changed files with 215 additions and 105 deletions

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SqlSugar;
using OrmTest.Models;
namespace OrmTest.Demo
{
public class ExtSqlFun : DemoBase
{
public static SqlSugarClient GetDb()
{
//Create ext method
var expMethods = new List<SqlFuncExternal>();
expMethods.Add(new SqlFuncExternal()
{
UniqueMethodName = "MyToString",
MethodValue = (expInfo, dbType, expContext) =>
{
return string.Format("CAST({0} AS VARCHAR(MAX))", expInfo.Args[0].MemberName);
}
});
var config = new ConnectionConfig()
{
ConnectionString = Config.ConnectionString,
DbType = DbType.SqlServer,
IsAutoCloseConnection = true,
ConfigureExternalServices = new ConfigureExternalServices()
{
SqlFuncServices = expMethods//set ext method
}
};
SqlSugarClient db = new SqlSugarClient(config);
return db;
}
public static string MyToString<T>(T str)
{
throw new NotSupportedException("Can only be used in expressions");
}
public static void Init()
{
var db = GetDb();
var list = db.Queryable<Student>().Where(it => MyToString(it.Id) == "1302583").ToList();
var sql = db.Queryable<Student>().Where(it => MyToString(it.Id) == "1302583").ToSql();
Console.WriteLine(sql);
}
}
}

View File

@@ -48,6 +48,7 @@ namespace OrmTest
OrmTest.Demo.Aop.Init(); OrmTest.Demo.Aop.Init();
OrmTest.Demo.MasterSlave.Init(); OrmTest.Demo.MasterSlave.Init();
OrmTest.Demo.SharedConnection.Init(); OrmTest.Demo.SharedConnection.Init();
OrmTest.Demo.ExtSqlFun.Init();
} }
} }
} }

View File

@@ -56,6 +56,7 @@
<Compile Include="Demos\4_Delete.cs" /> <Compile Include="Demos\4_Delete.cs" />
<Compile Include="Demos\9_Aop.cs" /> <Compile Include="Demos\9_Aop.cs" />
<Compile Include="Demos\B_SharedConnection.cs" /> <Compile Include="Demos\B_SharedConnection.cs" />
<Compile Include="Demos\C_ExtSqlFun.cs" />
<Compile Include="Demos\DemoBase.cs" /> <Compile Include="Demos\DemoBase.cs" />
<Compile Include="Demos\3_Insert.cs" /> <Compile Include="Demos\3_Insert.cs" />
<Compile Include="Demos\1_Query.cs" /> <Compile Include="Demos\1_Query.cs" />

View File

@@ -148,6 +148,7 @@ namespace SqlSugar
resolveExpress.MappingColumns = Context.MappingColumns; resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables; resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns; resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
resolveExpress.Resolve(expression, resolveType); resolveExpress.Resolve(expression, resolveType);
if (this.Parameters == null) if (this.Parameters == null)
this.Parameters = new List<SugarParameter>(); this.Parameters = new List<SugarParameter>();

View File

@@ -102,6 +102,7 @@ namespace SqlSugar
resolveExpress.MappingColumns = Context.MappingColumns; resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables; resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns; resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
resolveExpress.Resolve(expression, resolveType); resolveExpress.Resolve(expression, resolveType);
this.Parameters.AddRange(resolveExpress.Parameters); this.Parameters.AddRange(resolveExpress.Parameters);
var reval = resolveExpress.Result; var reval = resolveExpress.Result;

View File

@@ -216,12 +216,14 @@ namespace SqlSugar
resolveExpress.MappingColumns = Context.MappingColumns; resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables; resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns; resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
resolveExpress.InitMappingInfo = this.Context.InitMppingInfo; resolveExpress.InitMappingInfo = this.Context.InitMppingInfo;
resolveExpress.RefreshMapping = () => resolveExpress.RefreshMapping = () =>
{ {
resolveExpress.MappingColumns = Context.MappingColumns; resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables; resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns; resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
}; };
resolveExpress.Resolve(expression, resolveType); resolveExpress.Resolve(expression, resolveType);
this.Parameters.AddRange(resolveExpress.Parameters); this.Parameters.AddRange(resolveExpress.Parameters);

View File

@@ -118,6 +118,7 @@ namespace SqlSugar
resolveExpress.MappingColumns = Context.MappingColumns; resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables; resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns; resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
} }
resolveExpress.Resolve(expression, resolveType); resolveExpress.Resolve(expression, resolveType);
this.Parameters.AddRange(resolveExpress.Parameters); this.Parameters.AddRange(resolveExpress.Parameters);

View File

@@ -83,5 +83,7 @@ namespace SqlSugar
} }
set { _DataInfoCache = value; } set { _DataInfoCache = value; }
} }
public List<SqlFuncExternal> SqlFuncServices { get; set; }
} }
} }

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SqlSugar
{
public class SqlFuncExternal
{
public string UniqueMethodName { get; set; }
public Func<MethodCallExpressionModel, DbType, ExpressionContext, string> MethodValue { get; set; }
}
}

View File

@@ -41,6 +41,7 @@ namespace SqlSugar
public MappingColumnList MappingColumns { get; set; } public MappingColumnList MappingColumns { get; set; }
public MappingTableList MappingTables { get; set; } public MappingTableList MappingTables { get; set; }
public IgnoreColumnList IgnoreComumnList { get; set; } public IgnoreColumnList IgnoreComumnList { get; set; }
public List<SqlFuncExternal> SqlFuncServices { get; set; }
public bool IsSingle public bool IsSingle
{ {
get get

View File

@@ -256,6 +256,7 @@ namespace SqlSugar
newContext.MappingColumns = this.Context.MappingColumns; newContext.MappingColumns = this.Context.MappingColumns;
newContext.MappingTables = this.Context.MappingTables; newContext.MappingTables = this.Context.MappingTables;
newContext.IgnoreComumnList = this.Context.IgnoreComumnList; newContext.IgnoreComumnList = this.Context.IgnoreComumnList;
newContext.SqlFuncServices = this.Context.SqlFuncServices;
newContext.Resolve(item, this.Context.IsJoin ? ResolveExpressType.WhereMultiple : ResolveExpressType.WhereSingle); newContext.Resolve(item, this.Context.IsJoin ? ResolveExpressType.WhereMultiple : ResolveExpressType.WhereSingle);
this.Context.Index = newContext.Index; this.Context.Index = newContext.Index;
this.Context.ParameterIndex = newContext.ParameterIndex; this.Context.ParameterIndex = newContext.ParameterIndex;

View File

@@ -14,7 +14,7 @@ namespace SqlSugar
var express = base.Expression as MethodCallExpression; var express = base.Expression as MethodCallExpression;
var isLeft = parameter.IsLeft; var isLeft = parameter.IsLeft;
string methodName = express.Method.Name; string methodName = express.Method.Name;
var isValidNativeMethod = MethodMapping.ContainsKey(methodName) && express.Method.DeclaringType.Namespace == ("System"); var isValidNativeMethod = IsValidNativeMethod(express, methodName);
List<MethodCallExpressionArgs> appendArgs = null; List<MethodCallExpressionArgs> appendArgs = null;
if (MethodTimeMapping.ContainsKey(methodName)) if (MethodTimeMapping.ContainsKey(methodName))
{ {
@@ -55,7 +55,8 @@ namespace SqlSugar
} }
return; return;
} }
else if (IsIfElse(express, methodName)) { else if (IsIfElse(express, methodName))
{
CaseWhenResolve caseResole = new CaseWhenResolve(express, this.Context, parameter.OppsiteExpression); CaseWhenResolve caseResole = new CaseWhenResolve(express, this.Context, parameter.OppsiteExpression);
var appendSql = caseResole.GetSql(); var appendSql = caseResole.GetSql();
if (this.Context.ResolveType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle)) if (this.Context.ResolveType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle))
@@ -83,6 +84,17 @@ namespace SqlSugar
} }
} }
private bool IsValidNativeMethod(MethodCallExpression express, string methodName)
{
return MethodMapping.ContainsKey(methodName) && express.Method.DeclaringType.Namespace == ("System");
}
private bool IsExtMethod(string methodName)
{
if (this.Context.SqlFuncServices == null) return false;
return this.Context.SqlFuncServices.Select(it => it.UniqueMethodName).Contains(methodName);
}
private bool IsIfElse(MethodCallExpression express, string methodName) private bool IsIfElse(MethodCallExpression express, string methodName)
{ {
if (methodName == "End"&& express.Object.Type==typeof(CaseWhen)) if (methodName == "End"&& express.Object.Type==typeof(CaseWhen))
@@ -342,110 +354,126 @@ namespace SqlSugar
private object GetMdthodValue(string name, MethodCallExpressionModel model) private object GetMdthodValue(string name, MethodCallExpressionModel model)
{ {
switch (name) if (IsExtMethod(name))
{ {
case "IIF": DbType type = DbType.SqlServer;
return this.Context.DbMehtods.IIF(model); if (this.Context is SqlServerExpressionContext)
case "HasNumber": type = DbType.SqlServer;
return this.Context.DbMehtods.HasNumber(model); else if (this.Context is MySqlExpressionContext)
case "HasValue": type = DbType.MySql;
return this.Context.DbMehtods.HasValue(model); else if (this.Context is SqliteExpressionContext)
case "IsNullOrEmpty": type = DbType.Sqlite;
return this.Context.DbMehtods.IsNullOrEmpty(model); else if(this.Context is OracleExpressionContext)
case "ToLower": type = DbType.Oracle;
return this.Context.DbMehtods.ToLower(model); return this.Context.SqlFuncServices.First(it => it.UniqueMethodName == name).MethodValue(model,type,this.Context);
case "ToUpper": }
return this.Context.DbMehtods.ToUpper(model); else
case "Trim": {
return this.Context.DbMehtods.Trim(model); switch (name)
case "Contains": {
return this.Context.DbMehtods.Contains(model); case "IIF":
case "ContainsArray": return this.Context.DbMehtods.IIF(model);
var caResult = this.Context.DbMehtods.ContainsArray(model); case "HasNumber":
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); return this.Context.DbMehtods.HasNumber(model);
return caResult; case "HasValue":
case "Equals": return this.Context.DbMehtods.HasValue(model);
return this.Context.DbMehtods.Equals(model); case "IsNullOrEmpty":
case "DateIsSame": return this.Context.DbMehtods.IsNullOrEmpty(model);
if (model.Args.Count == 2) case "ToLower":
return this.Context.DbMehtods.DateIsSameDay(model); return this.Context.DbMehtods.ToLower(model);
else case "ToUpper":
{ return this.Context.DbMehtods.ToUpper(model);
var dsResult = this.Context.DbMehtods.DateIsSameByType(model); case "Trim":
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString()); return this.Context.DbMehtods.Trim(model);
return dsResult; case "Contains":
} return this.Context.DbMehtods.Contains(model);
case "DateAdd": case "ContainsArray":
if (model.Args.Count == 2) var caResult = this.Context.DbMehtods.ContainsArray(model);
return this.Context.DbMehtods.DateAddDay(model); this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString());
else return caResult;
{ case "Equals":
var daResult = this.Context.DbMehtods.DateAddByType(model); return this.Context.DbMehtods.Equals(model);
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString()); case "DateIsSame":
return daResult; if (model.Args.Count == 2)
} return this.Context.DbMehtods.DateIsSameDay(model);
case "DateValue": else
var dvResult = this.Context.DbMehtods.DateValue(model); {
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString()); var dsResult = this.Context.DbMehtods.DateIsSameByType(model);
return dvResult; this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString());
case "Between": return dsResult;
return this.Context.DbMehtods.Between(model); }
case "StartsWith": case "DateAdd":
return this.Context.DbMehtods.StartsWith(model); if (model.Args.Count == 2)
case "EndsWith": return this.Context.DbMehtods.DateAddDay(model);
return this.Context.DbMehtods.EndsWith(model); else
case "ToInt32": {
return this.Context.DbMehtods.ToInt32(model); var daResult = this.Context.DbMehtods.DateAddByType(model);
case "ToInt64": this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString());
return this.Context.DbMehtods.ToInt64(model); return daResult;
case "ToDate": }
return this.Context.DbMehtods.ToDate(model); case "DateValue":
case "ToTime": var dvResult = this.Context.DbMehtods.DateValue(model);
return this.Context.DbMehtods.ToTime(model); this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString());
case "ToString": return dvResult;
Check.Exception(model.Args.Count > 1, "ToString (Format) is not supported, Use ToString().If time formatting can be used it.Date.Year+\"-\"+it.Data.Month+\"-\"+it.Date.Day "); case "Between":
return this.Context.DbMehtods.ToString(model); return this.Context.DbMehtods.Between(model);
case "ToDecimal": case "StartsWith":
return this.Context.DbMehtods.ToDecimal(model); return this.Context.DbMehtods.StartsWith(model);
case "ToGuid": case "EndsWith":
return this.Context.DbMehtods.ToGuid(model); return this.Context.DbMehtods.EndsWith(model);
case "ToDouble": case "ToInt32":
return this.Context.DbMehtods.ToDouble(model); return this.Context.DbMehtods.ToInt32(model);
case "ToBool": case "ToInt64":
return this.Context.DbMehtods.ToBool(model); return this.Context.DbMehtods.ToInt64(model);
case "Substring": case "ToDate":
return this.Context.DbMehtods.Substring(model); return this.Context.DbMehtods.ToDate(model);
case "Replace": case "ToTime":
return this.Context.DbMehtods.Replace(model); return this.Context.DbMehtods.ToTime(model);
case "Length": case "ToString":
return this.Context.DbMehtods.Length(model); Check.Exception(model.Args.Count > 1, "ToString (Format) is not supported, Use ToString().If time formatting can be used it.Date.Year+\"-\"+it.Data.Month+\"-\"+it.Date.Day ");
case "AggregateSum": return this.Context.DbMehtods.ToString(model);
return this.Context.DbMehtods.AggregateSum(model); case "ToDecimal":
case "AggregateAvg": return this.Context.DbMehtods.ToDecimal(model);
return this.Context.DbMehtods.AggregateAvg(model); case "ToGuid":
case "AggregateMin": return this.Context.DbMehtods.ToGuid(model);
return this.Context.DbMehtods.AggregateMin(model); case "ToDouble":
case "AggregateMax": return this.Context.DbMehtods.ToDouble(model);
return this.Context.DbMehtods.AggregateMax(model); case "ToBool":
case "AggregateCount": return this.Context.DbMehtods.ToBool(model);
return this.Context.DbMehtods.AggregateCount(model); case "Substring":
case "MappingColumn": return this.Context.DbMehtods.Substring(model);
var mappingColumnResult = this.Context.DbMehtods.MappingColumn(model); case "Replace":
var isValid = model.Args[0].IsMember && model.Args[1].IsMember == false; return this.Context.DbMehtods.Replace(model);
Check.Exception(!isValid, "SqlFunc.MappingColumn parameters error, The property name on the left, string value on the right"); case "Length":
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString()); return this.Context.DbMehtods.Length(model);
return mappingColumnResult; case "AggregateSum":
case "IsNull": return this.Context.DbMehtods.AggregateSum(model);
return this.Context.DbMehtods.IsNull(model); case "AggregateAvg":
case "MergeString": return this.Context.DbMehtods.AggregateAvg(model);
return this.Context.DbMehtods.MergeString(model.Args.Select(it=>it.MemberName.ObjToString()).ToArray()); case "AggregateMin":
case "GetSelfAndAutoFill": return this.Context.DbMehtods.AggregateMin(model);
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); case "AggregateMax":
return this.Context.DbMehtods.GetSelfAndAutoFill(model.Args[0].MemberValue.ObjToString(), this.Context.IsSingle); return this.Context.DbMehtods.AggregateMax(model);
case "GetDate": case "AggregateCount":
return this.Context.DbMehtods.GetDate(); return this.Context.DbMehtods.AggregateCount(model);
default: case "MappingColumn":
break; var mappingColumnResult = this.Context.DbMehtods.MappingColumn(model);
var isValid = model.Args[0].IsMember && model.Args[1].IsMember == false;
Check.Exception(!isValid, "SqlFunc.MappingColumn parameters error, The property name on the left, string value on the right");
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString());
return mappingColumnResult;
case "IsNull":
return this.Context.DbMehtods.IsNull(model);
case "MergeString":
return this.Context.DbMehtods.MergeString(model.Args.Select(it => it.MemberName.ObjToString()).ToArray());
case "GetSelfAndAutoFill":
this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString());
return this.Context.DbMehtods.GetSelfAndAutoFill(model.Args[0].MemberValue.ObjToString(), this.Context.IsSingle);
case "GetDate":
return this.Context.DbMehtods.GetDate();
default:
break;
}
} }
return null; return null;
} }
@@ -495,6 +523,7 @@ namespace SqlSugar
} }
private void CheckMethod(MethodCallExpression expression) private void CheckMethod(MethodCallExpression expression)
{ {
if (IsExtMethod(expression.Method.Name)) return;
Check.Exception(expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName, string.Format(ErrorMessage.MethodError, expression.Method.Name)); Check.Exception(expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName, string.Format(ErrorMessage.MethodError, expression.Method.Name));
} }
} }

View File

@@ -38,6 +38,7 @@ namespace SqlSugar
newContext.MappingColumns = context.MappingColumns; newContext.MappingColumns = context.MappingColumns;
newContext.MappingTables = context.MappingTables; newContext.MappingTables = context.MappingTables;
newContext.IgnoreComumnList = context.IgnoreComumnList; newContext.IgnoreComumnList = context.IgnoreComumnList;
newContext.SqlFuncServices = context.SqlFuncServices;
newContext.Resolve(item, type); newContext.Resolve(item, type);
context.Index = newContext.Index; context.Index = newContext.Index;
context.ParameterIndex = newContext.ParameterIndex; context.ParameterIndex = newContext.ParameterIndex;

View File

@@ -11,6 +11,8 @@ namespace SqlSugar
MappingColumnList MappingColumns { get; set; } MappingColumnList MappingColumns { get; set; }
MappingTableList MappingTables { get; set; } MappingTableList MappingTables { get; set; }
IgnoreColumnList IgnoreComumnList { get; set; } IgnoreColumnList IgnoreComumnList { get; set; }
List<SqlFuncExternal> SqlFuncServices { get; set; }
List<JoinQueryInfo> JoinQueryInfos { get; set; } List<JoinQueryInfo> JoinQueryInfos { get; set; }
bool IsSingle { get; set; } bool IsSingle { get; set; }
SqlSugarClient Context { get; set; } SqlSugarClient Context { get; set; }

View File

@@ -82,6 +82,7 @@
<Compile Include="Enum\DbType.cs" /> <Compile Include="Enum\DbType.cs" />
<Compile Include="ExpressionsToSql\CaseWhen\CaseWhen.cs" /> <Compile Include="ExpressionsToSql\CaseWhen\CaseWhen.cs" />
<Compile Include="ExpressionsToSql\CaseWhen\CaseWhenResolve.cs" /> <Compile Include="ExpressionsToSql\CaseWhen\CaseWhenResolve.cs" />
<Compile Include="ExpressionsToSql\DbMethods\SqlFuncExternal.cs" />
<Compile Include="ExpressionsToSql\Subquery\Items\ISubOperation.cs" /> <Compile Include="ExpressionsToSql\Subquery\Items\ISubOperation.cs" />
<Compile Include="ExpressionsToSql\Subquery\Items\SubAnd.cs" /> <Compile Include="ExpressionsToSql\Subquery\Items\SubAnd.cs" />
<Compile Include="ExpressionsToSql\Subquery\Items\SubCount.cs" /> <Compile Include="ExpressionsToSql\Subquery\Items\SubCount.cs" />