sqlsugar入门(4)-修改源码支持多主键保存ISaveable
1.查看其它接口发现少了一个最重要的SaveBuilder。此文件是存放sql模板,where条件,select解析,组装成tosqlstring的最后一个类。
添加文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions; namespace SqlSugar
{
public class SaveBuilder : IDMLBuilder
{
public SaveBuilder()
{
this.sql = new StringBuilder();
this.DbColumnInfoList = new List<DbColumnInfo>();
this.SetValues = new List<KeyValuePair<string, string>>();
this.WhereValues = new List<string>();
this.Parameters = new List<SugarParameter>();
}
public SqlSugarProvider Context { get; set; }
public ILambdaExpressions LambdaExpressions { get; set; }
public ISqlBuilder Builder { get; set; }
public StringBuilder sql { get; set; }
public List<SugarParameter> Parameters { get; set; }
public string TableName { get; set; }
public string TableWithString { get; set; }
public List<DbColumnInfo> DbColumnInfoList { get; set; }
public List<string> WhereValues { get; set; }
public List<KeyValuePair<string, string>> SetValues { get; set; }
public bool IsNoUpdateNull { get; set; }
public bool IsNoUpdateDefaultValue { get; set; }
public List<string> PrimaryKeys { get; set; }
public bool IsOffIdentity { get; set; }
public bool IsWhereColumns { get; set; } /// <summary>
/// select x as X as a join T t on a.id = t.id
/// </summary> public virtual string SqlTemplate
{
get
{
return @"UPDATE {0} SET
{1} {2}"; }
} public virtual string SqlTemplateBatch
{
get
{
return @" SELECT {3} FROM (
{0} ) T ,{1} S WHERE {2}
; ";
}
} public virtual string SqlTemplateBatchSelect
{
get
{
return "{0} AS {1}";
}
} public virtual string SqlTemplateBatchUnion
{
get
{
return "\t\t\r\nUNION ALL ";
}
} public virtual void Clear()
{ }
public virtual string GetTableNameString
{
get
{
var result = Builder.GetTranslationTableName(TableName);
result += UtilConstants.Space;
if (this.TableWithString.HasValue())
{
result += TableWithString + UtilConstants.Space;
}
return result;
}
}
public virtual string GetTableNameStringNoWith
{
get
{
var result = Builder.GetTranslationTableName(TableName);
return result;
}
} public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType, bool isMapping = true)
{
ILambdaExpressions resolveExpress = this.LambdaExpressions;
this.LambdaExpressions.Clear();
if (this.Context.CurrentConnectionConfig.MoreSettings != null)
{
resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower;
}
else
{
resolveExpress.PgSqlIsAutoToLower = true;
}
if (isMapping)
{
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
}
resolveExpress.InitMappingInfo = Context.InitMappingInfo;
resolveExpress.RefreshMapping = () =>
{
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
};
resolveExpress.Resolve(expression, resolveType);
this.Parameters.AddRange(resolveExpress.Parameters);
var result = resolveExpress.Result;
return result;
}
public virtual string ToSqlString()
{
if (IsNoUpdateNull)
{
DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList();
}
if (IsNoUpdateDefaultValue)
{
DbColumnInfoList = DbColumnInfoList.Where(it => it.Value.ObjToString() !=UtilMethods.DefaultForType(it.PropertyType).ObjToString()).ToList();
}
var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); return TomultipleSqlString(groupList);
} protected virtual string TomultipleSqlString(List<IGrouping<int, DbColumnInfo>> groupList)
{
Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List<T> need Primary key"); StringBuilder batchUpdateSql = new StringBuilder(); StringBuilder updateTable = new StringBuilder(); string selectString = string.Join(",", groupList.First().Select(
it =>
{
var result = "S." + it.DbColumnName + " " + Builder.GetTranslationColumnName(it.DbColumnName);
return result;
}
)); int i = 0;
foreach (var columns in groupList)
{
var isFirst = i == 0;
if (!isFirst)
{
updateTable.Append(SqlTemplateBatchUnion);
}
updateTable.Append("\r\n SELECT " + string.Join(",", columns.Where(o=>this.PrimaryKeys.Contains(o.DbColumnName)).Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName)))));
++i;
}
updateTable.Append("\r\n");
string whereString = null;
//if (this.WhereValues.HasValue())
//{
// foreach (var item in WhereValues)
// {
// var isFirst = whereString == null;
// whereString += (isFirst ? null : " AND ");
// whereString += Regex.Replace(item, "\\" + this.Builder.SqlTranslationLeft, "S." + this.Builder.SqlTranslationLeft);
// }
//}
if (PrimaryKeys.HasValue())
{
foreach (var item in PrimaryKeys)
{
var isFirst = whereString == null;
whereString += (isFirst ? null : " AND ");
whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item));
}
}
batchUpdateSql.AppendFormat(SqlTemplateBatch, updateTable,this.TableName , whereString, selectString); return batchUpdateSql.ToString();
} public virtual object FormatValue(object value)
{
if (value == null)
{
return "NULL";
}
else
{
var type = UtilMethods.GetUnderType(value.GetType());
if (type == UtilConstants.DateType)
{
var date = value.ObjToDate();
if (date < Convert.ToDateTime("1900-1-1"))
{
date = Convert.ToDateTime("1900-1-1");
}
return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
}
else if (type == UtilConstants.ByteArrayType)
{
string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", "");
return bytesString;
}
else if (type.IsEnum())
{
return Convert.ToInt64(value);
}
else if (type == UtilConstants.BoolType)
{
return value.ObjToBool() ? "1" : "0";
}
else if (type == UtilConstants.StringType || type == UtilConstants.ObjType)
{
return "N'" + value.ToString().ToSqlFilter() + "'";
}
else
{
return "N'" + value.ToString() + "'";
}
}
}
}
}
2.修改SaveableProvider<T>使单主键查询数据库改为按条件解析查询existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
3.添加动态表达式来筛选更新的数据以及插入的数据。
public List<T> insertObjects
{
get
{
var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation;
this.Context.Ado.IsDisableMasterSlaveSeparation = true;
List<T> result = new List<T>();
var pks = GetPrimaryKeys();
Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false)
.Where(it => pks.Contains(it.DbColumnName)).ToList();
if (existsObjects == null)
{
SaveBuilder.PrimaryKeys = pks;
existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
}
this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation;
ParameterExpression param1 = Expression.Parameter(typeof(T), "it");
ParameterExpression param = Expression.Parameter(typeof(T), "e");
BinaryExpression mainBinaryExpression = null;
foreach (var info in pkInfo)
{
MemberExpression body = Expression.PropertyOrField(param, info.PropertyName);
MemberExpression body1 = Expression.PropertyOrField(param1, info.PropertyName);
var exp = Expression.Equal(body, body1); if (mainBinaryExpression == null)
{
mainBinaryExpression = exp;
}
else
{
mainBinaryExpression = Expression.AndAlso(mainBinaryExpression, exp);
}
}
var lambda = Expression.Lambda<Func<T, Boolean>>(mainBinaryExpression, new[] { param });
Expression anyExpression = Expression.Call(
typeof(Enumerable), "Any",
new Type[] { typeof(T) },
Expression.Constant(existsObjects), lambda
);
var lambda1 = Expression.Lambda<Func<T, Boolean>>(Expression.Not(anyExpression), new[] { param1 });
return saveObjects.Where(lambda1.Compile()).ToList();
}
}
public List<T> updatObjects
{
get
{
var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation;
this.Context.Ado.IsDisableMasterSlaveSeparation = true;
List<T> result = new List<T>();
var pks = GetPrimaryKeys();
Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false)
.Where(it => pks.Contains(it.DbColumnName)).ToList();
if (existsObjects == null)
{
SaveBuilder.PrimaryKeys = pks;
existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
}
this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation;
ParameterExpression param1 = Expression.Parameter(typeof(T), "it");
ParameterExpression param = Expression.Parameter(typeof(T), "e");
BinaryExpression mainBinaryExpression = null;
foreach (var info in pkInfo)
{
MemberExpression body = Expression.PropertyOrField(param, info.PropertyName);
MemberExpression body1 = Expression.PropertyOrField(param1, info.PropertyName);
var exp = Expression.Equal(body, body1); if (mainBinaryExpression == null)
{
mainBinaryExpression = exp;
}
else
{
mainBinaryExpression = Expression.AndAlso(mainBinaryExpression, exp);
}
}
var lambda = Expression.Lambda<Func<T, Boolean>>(mainBinaryExpression, new[] { param });
Expression anyExpression = Expression.Call(
typeof(Enumerable), "Any",
new Type[] { typeof(T) },
Expression.Constant(existsObjects), lambda
);
var lambda1 = Expression.Lambda<Func<T, Boolean>>(anyExpression, new[] { param1 });
return saveObjects.Where(lambda1.Compile()).ToList();
}
}
4.添加tosql来打印生成的sql
ISaveable 添加tosql接口
List<KeyValuePair<string, List<SugarParameter>>> ToSql();
SaveableProvider实现接口
public List<KeyValuePair<string, List<SugarParameter>>> ToSql()
{
List<KeyValuePair<string, List<SugarParameter>>> sqllist = new List<KeyValuePair<string, List<SugarParameter>>>();
LoadInsertable();
LoadUpdateable();
if (insertable != null)
{
var insertsql = insertable.ToSql();
sqllist.Add(insertsql);
}
if (updateable != null)
{
var updatesql = updateable.ToSql();
sqllist.Add(updatesql);
} return sqllist;
}
Demo地址:https://gitee.com/xuanyun2018/sqlsugardemo.git
下一章节扩展分库分表功能。
sqlsugar入门(4)-修改源码支持多主键保存ISaveable的更多相关文章
- ok6410 u-boot-2012.04.01移植二修改源码支持单板
继ok6410 u-boot-2012.04.01移植一后修改代码,对ok6410单板初始化,主要包括时钟.串口.NAND.DDR等初始化.这些工作在以前的裸板程序都写了,直接拿来用.我觉得先写裸板程 ...
- 修改Cosbench源码 支持s3的 http range request 测试场景
在视频点播的业务应用场景中,用户使用了ffmpeg工具做视频实时转码用. 而ffmpeg使用range 请求.而Cosbench不支持这种测试场景,所以需要修改源码支持这种测试场景. HTTP 协议介 ...
- Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持
下面开始添加国产卫星光谱响应的支持: 以下主要参考文章“6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)”网址:http://blog.csdn.net/sam92/art ...
- 修改json源码支持datetime序列化
修改json源码支持datetime序列化 import json import datetime now = datetime.datetime.today() json.dumps(now) 抛出 ...
- Python paramiko 修改源码实现用户命令抓取
paramiko 源码修改 paramiko主要用来实现ssh客户端.服务端链接,上一节我们说到了堡垒机,堡垒机内有一个需求是“用户行为审计”,在这里我们就可以通过修改paramiko内文件的源码来实 ...
- Android5.1.1 - APK签名校验分析和修改源码绕过签名校验
Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...
- mvcAPI (入门 3)(源码)
mvcAPI (入门 3)(源码) http://download.csdn.net/detail/chunfang740/9078579
- element-ui 修改源码实践 --tranfer
1.element-ui 地址:https://github.com/ElemeFE/element 2.修改elelment-ui版本:2.2.2(请选择和项目相对应的版本) 3.修改内容:穿梭框组 ...
- zookeeper-如何修改源码-《每日五分钟搞定大数据》
本篇文章仅仅是起一个抛砖迎玉的作用,举一个如何修改源码的例子.文章的灵感来自 ZOOKEEPER-2784. 提一个问题先 之前的文章讲过zxid的设计,我们先复习下: zxid有64位,分成两部分: ...
随机推荐
- WordPress用户角色权限
[转自:群燕小站(http://www.zqunyan.com):原文链接: http://www.zqunyan.com/158.html] WordPress默认的用户角色有5个:订阅者,投稿者, ...
- windows 10 启动修复无法自动修复此计算机
1. 失败后有两个选项卡:关机和高级选项,选择高级选项 2. 然后选择疑难解答 3. 选择高级选项 4. 选择回退到以前的版本 接下来需要登录,选择恢复到上一次正常启动的状态,注意选择保留数据,会有提 ...
- Java知识系统回顾整理01基础02面向对象01类和对象
一.面向对象实例--设计英雄这个类 LOL有很多英雄,比如盲僧,团战可以输,提莫必须死,盖伦,琴女 所有这些英雄,都有一些共同的状态 比如,他们都有名字,hp,护甲,移动速度等等 这样我们就可以设计一 ...
- nessus 本地扫描(一)
第一次使用nessus ,so 适合小白看看 1.新建扫描.配置策略:起个名字,description是详细记录,类似于说明:targets是要访问的主机ip地址或者网段,必填项 选择好之后sav ...
- BSGS算法解析
前置芝士: 1.快速幂(用于求一个数的幂次方) 2.STL里的map(快速查找) 详解 BSGS 算法适用于解决高次同余方程 \(a^x\equiv b (mod p)\) 由费马小定理可得 x &l ...
- winfrom加载自定义控件、窗口pannel后闪烁问题
我用一个panel当容器,里面有好多控件,加载的时候一直闪烁. 借鉴网友的思路: 窗口初始化界面加入代码 this.DoubleBuffered = true;//设置本窗体 SetStyle(C ...
- 这个网易云JS解密,老网抑云看了都直呼内行
最近更新频率慢了,这不是因为CK3发售了嘛,一个字就是"肝".今天来看一下网易云音乐两个加密参数params和encSecKey,顺便抓取一波某歌单的粉丝,有入库哦,使用mysql ...
- Github 太狠了,居然把 "master" 干掉了!
前段时间栈长有看到 Github 和 master 分支变更的新闻,当时没有注意细节,直到今天我创建仓库时: 看了半天感觉有点不对劲啊... 怎么 master 不见了,之前默认主干分支名称都是叫 m ...
- Python日志采集(详细)
通常在前期调试代码的时候,我们会使用print在IDE控制台打印一些信息,判断运行情况.但在运行整个自动化测试项目的过程中,通过print打印信息的方式获取运行情况显然行不通. 这时就需要收集日志,每 ...
- Python数据类型--集合(set)
Python的集合是无序.可迭代的容器对象,所有元素放在一对大括号中{},元素之间使用逗号隔开,同一集合内的元素具有唯一性,不允许重复. 集合中只能包含数字.字符串.元组等不可变类型的数据,不能包含列 ...