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

下一章节扩展分库分表功能。

 

版权声明:本文为yangzai2020原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yangzai2020/p/13828961.html