zoukankan      html  css  js  c++  java
  • dapper.common新增概念object to sql

    Dapper.Common
    About author
    Email:1448376744@qq.com
    QQ:1448376744
    QQGroup:642555086
    Config
     DbContextFactory.AddDataSource(new DataSource()
     {
         Default = true,
         Name = "mysql",
         ConnectionFacotry = () => new MySql.Data.MySqlClient.MySqlConnection("server=localhost;user id=root;password=1024;database=test;"),
         DatasourceType = DatasourceType.MYSQL,
         UseProxy = true//use static proxy,for logger
     });
    Insert
    IDbContext context = null;
    try
    {
        context = DbContextFactory.GetDbContext();
        //because set "id[isIdentity=true]",so not set "id" value
        var row1 = context.From<Student>().Insert(new Student()
        {
            Grade = Grade.A,
            CreateTime = DateTime.Now,
            Name = "jack",
        });
        //batch added
        var row2 = context.From<Student>().Insert(new List<Student>()
        {
            new Student()
            {
                Grade = Grade.C,
                CreateTime = DateTime.Now,
                Name = "tom",
            },
             new Student()
            {
                Grade = Grade.F,
                CreateTime = DateTime.Now,
                Name = "jar",
            },
        });
    }
    catch (Exception e)
    {
        //debug sql logger
        Console.WriteLine(context.Loggers);
    }
    finally
    {
        context.Close();
    }
    Update
    using (var context = DbContextFactory.GetDbContext())
    {
        //param
        var age = 20;
        DateTime? time = null;
        var sid = 1;
    
        //subquery
        var subquery = new SubQuery<School>()
            .Where(a => a.Id == sid)
            .Select(s => s.Name);
    
        var row1 = context.From<Student>()
            .Set(a => a.Age, a => a.Age + age)
            .Set(a => a.Name, subquery)
            .Set(a => a.CreateTime, time, time != null)
            .Where(a => a.Id == 16)
            .Update();
    
        //function
        context.From<Student>()
            .Set(a => a.Name, a => MysqlFun.REPLACE(a.Name, "a", "b"))
            .Where(a => a.Id == 14)
            .Update();
    
        //lock
        var student = context.From<Student>()
            .Where(a => a.Id == 16)
            .Single();
        var row2 = context.From<Student>()
            .Set(a => a.Age, 80)
            .Set(a => a.Version, Guid.NewGuid().ToString())
            .Where(a => a.Id == 16 && a.Version == student.Version)
            .Update();
    
        //entity
        var row3 = context.From<Student>()
            .Filter(a => a.SchoolId)
            .Update(new Student()
            {
                Id = 2,
                CreateTime = DateTime.Now
            });
    Delete
    using (var context = DbContextFactory.GetDbContext())
    {
        var row1 = context.From<Student>()
             .Where(a => a.Id == 16)
             .Delete();
    
        var subquery = new SubQuery<School>()
            .Where(a => a.Id >= 0)
            .Select(a => a.Id);
    
        var row2 = context.From<Student>()
             .Where(a => Operator.In(a.Id, subquery))
             .Delete();
    }
    Transaction
      IDbContext dbContext = null;
      try
      {
          dbContext = DbContextFactory.GetDbContext();
          dbContext.Open(true);
          dbContext.From<Student>().Insert(new Student()
          {
              Name="stduent1"
          });
          //throw new Exception("rollback");
          dbContext.From<School>().Insert(new School()
          {
              Name = "school1"
          });
          dbContext.Commit();
      }
      catch (Exception)
      {
          dbContext?.Rollback();
          throw;
      }
      finally
      {
          dbContext?.Close();
      }
    Select
     //single
     var student = context.From<Student>()
         .Where(a => a.Id == 19)
         .Single();
    
     //subquery
     var id = 0;
     var age = 50;
     var subquery = new SubQuery<School>()
        .Where(a => a.Id >= id)
        .Select(a => a.Id);
    
     //Verify that subquery parameters are written to the current query
     var students2 = context.From<Student>()
         .OrderBy(a => a.Age)
         .Where(a => a.Id >= Operator.Any(subquery) && a.Age > age)
         .Select();
    
     //Partial columns
     var students3 = context.From<Student>()
        .Select(s => new
        {
            s.Id,
            s.Age
        });
    Group by
      var students = context.From<Student>()
          .GroupBy(a => a.Age)
          .Having(a => MysqlFun.Count(1L) > 2)
          .Select(s => new
          {
              Count = MysqlFun.Count(1L),
              s.Age,
          });
    Dynamic query
    var param = new Student()
    {
        Name = "zs",
        Grade = Grade.B,
        SchoolId = null,
        Id = null,
        Type = 5
    };
    
    //Multiple Where Connections with AND
    var students = context.From<Student>()
        .Where(a => a.Id == param.Id, param.Id != null)
        .Where(a => Operator.Contains(a.Name, param.Name), param.Name != null)
        .Where(a => a.Grade == param.Grade, param.Grade != null)
        .Where(a => a.Id > 2 || a.Age < 80, param.Type == 5)
        .Select();
    
    
    var students2 = context.From<Student>()
        .Where(a => a.Id == param.Id, param.Id != null)
        .Where(a => a.Grade == param.Grade, param.Grade != null)
        .Where(a => Operator.StartsWith(a.Name, param.Name), param.Name != null)
        .Where(a => a.Id > 2 || a.Age > 20, param.Type == 8)
        .Select();
    Task page
     var students = context.From<Student>()
         .Page(1, 10, out long total)
         .Select();
    Join
     var students = context.From<Student, School>()
         .Join((a, b) => a.SchoolId == b.Id)
         .Select((a, b) => new
         {
             a.Id,
             StuName = a.Name,
             SchName = b.Name
         });
    Other query
    //limit 0,10
    var students1 = context.From<Student>()
        .Take(10)
        .Select();
    
    //limit 10,20 
    var students2 = context.From<Student>()
       .Skip(10, 20)
       .Select();
    
    //Calling functions in expressions is not recommended, but n-tier attribute access is supported
    var student3 = context.From<Student>()
        .Where(a => a.CreateTime == DateTime.Now.Date)
        .Select();
    //lock
    var students4 = context.From<Student>()
       .With(LockType.FOR_UPADTE)
       .Select();    
       
    //exists1
    var flag1 = context.From<Student>()
        .Where(a => a.Id > 50)
        .Exists();
    
    //exists2
    var subquery = new SubQuery<School>()
        .Where(a => a.Id >= 2)
        .Select(a => a.Id);
    var flag2 = context.From<Student>()
        .Where(a => Operator.Exists(subquery))
        .Count();
    
    //count
    var count = context.From<Student>()
       .Where(a => a.Id > 50)
       .Count();
    
    //sum
    var sum = context.From<Student>()
     .Where(a => a.Id > 50)
     .Sum(s => s.Id * s.Age);
    
    //distinct
    var disinct = context.From<Student>()
        .Distinct()
        .Select(s => s.Name);
    Custom Function
    step1
     public static class MysqlFun
     {
         [Function]
         public static string REPLACE(string column,string oldstr,string newstr)
         {
             return string.Empty;
         }
         [Function]
         public static T Count<T>(T column)
         {
             return default;
         }
       
     }
    step2
     var students = context.From<Student>()
         .GroupBy(a => a.Age)
         .Having(a => MysqlFun.Count(1L) > 2)
         .Select(s => new
         {
             Count = MysqlFun.Count(1L),
             s.Age,
         });
    Expression To Sql
    var prefix = "@";
    var values = new Dictionary<string, object>();
    Expression<Func<Student,bool>> expression = s => s.Age>40; 
    var expression = ExpressionUtil.BuildExpression(item, expression, prefix);
    Object to Sql
    DEMO.1 Case When Then Else
    step1: implement
    //Dapper.common doesn't care how you implement it, it only concerns the result of build.
    public class Case<T> : ISqlBuilder
    {
        private List<Expression> _whens = new List<Expression>();
        private List<string> _thens = new List<string>();
        string _else = null;
        public string Build(Dictionary<string, object> values, string prefix)
        {
            var sb = new StringBuilder();
            foreach (var item in _whens)
            {
                var express = ExpressionUtil.BuildExpression(item, values, prefix);
                sb.AppendFormat(" WHEN {0} THEN '{1}'", express, _thens[_whens.IndexOf(item)]);
            }
            if (_else != null)
            {
                sb.AppendFormat(" ELSE '{0}'", _else);
            }
            return string.Format("(CASE {0} END)", sb);
        }
        public static implicit operator string(Case<T> d) => string.Empty;
        public Case<T> When(Expression<Func<T, bool>> expression)
        {
            new Dictionary<string, object>();
            _whens.Add(expression);
            return this;
        }
        public Case<T> Then(string value)
        {
            _thens.Add(value);
            return this;
        }
        public Case<T> Else(string value)
        {
            _else = value;
            return this;
        }
    }
    step2: use
    //case
    var caseWhen = new Case<Student>()
        .When(a => a.Age <= 18)
        .Then("children")
        .When(a => a.Age <= 40)
        .Then("Youth")
        .Else("Old");
    
    //The "caseWhen" object is still an ISqlBuild instance at run time, not a string
    //The engine passes in parameters and calls the "caseWhen.Build" method of the instance
    var students1 = context.From<Student>()
        .Where(a => caseWhen == "Old" || caseWhen == "Youth")
        .Select(s => new
        {
            s.Id,
            GroupAge = (string)caseWhen
        });
    DEMO.2 Complex Function
    step1: implement
     public class DateAdd<T> : ISqlBuilder
     {
         public string Column { get; set; }
         public int Expr { get; set; }
         public string Unit { get; set; }
         public Dictionary<string, object> Values { get; set; }
    
         public string Build(Dictionary<string, object> values, string prefix)
         {
             return "DATE_ADD(" + Column + ",INTERVAL " + Expr + " " + Unit + ")";
         }
         public DateAdd(Expression<Func<T, DateTime?>> column, int expr, string unit)
         {
             this.Column = ExpressionUtil.BuildColumn(column, null, null).FirstOrDefault().Value;
             this.Expr = expr;
             this.Unit = unit;
         }
         public static bool operator <(DateTime? t1, DateAdd<T> t2)
         {
             return false;
         }
         public static bool operator <(DateAdd<T> t1, DateTime? t2)
         {
             return false;
         }
         public static bool operator >(DateTime? t1, DateAdd<T> t2)
         {
             return false;
         }
         public static bool operator >(DateAdd<T> t1, DateTime? t2)
         {
             return false;
         }
         public static explicit operator DateTime(DateAdd<T> d) => DateTime.Now;
     }
    step2: use
     var adddayfun = new DateAdd<Student>(a => a.CreateTime, 1, "day");
    
     //in columus
     var student1 = context.From<Student>()
         .Select(s => new
         {
             s.Id,
             DateTime = (DateTime)adddayfun //just for type inference
         });
    
     //in expression
     var student2 = context.From<Student>()
         .Where(a => adddayfun > DateTime.Now)
         .Select();
    DEMO.3 Window Function
    step1: implement
     public class WinFun<T> : ISqlBuilder
     {
         string _partition { get; set; }
         string _orderby { get; set; }
         private string _methodName { get; set; }
         public WinFun<T> ROW_NUMBER()
         {
             _methodName = nameof(ROW_NUMBER);
             return this;
         }
         public WinFun<T> PARTITION<TResult>(Expression<Func<T, TResult>> columns)
         {
             var cls = ExpressionUtil.BuildColumns(columns, null, null);
             _partition += string.Join(",", cls.Select(s => s.Value));
             return this;
         }
         public WinFun<T> ORDERBY<TResult>(Expression<Func<T, TResult>> columns, bool asc = true)
         {
             var cls = ExpressionUtil.BuildColumns(columns, null, null);
             _orderby += string.Join(",", cls.Select(s => s.Value));
             _orderby += !asc ? "DESC" : "ASC";
             return this;
         }
         /*If there are no parameters in the expression, there is no need to build in build-method*/
         public string Build(Dictionary<string, object> values, string prefix)
         {
             if (_methodName == nameof(ROW_NUMBER))
             {
                 return string.Format("ROW_NUMBER()OVER(ORDER BY {0})", _orderby);
             }
             throw new NotImplementedException();
         }
    
         public static implicit operator ulong(WinFun<T> d) => 0;
     }
    step2: use
     var winFun = new WinFun<Student>()
         .ORDERBY(a => a.Age)
         .ROW_NUMBER();
    
     var student1 = context.From<Student>()
        .Select(s => new
        {
            s.Id,
            s.Name,
            s.Age,
            RowNum = (ulong)winFun
        });
        
    DEMO.4 Subquery
    step1: implement
    public class SubQuery<T> : ISubQuery where T : class
    {
        private Expression _where { get; set; }
        private Expression _column { get; set; }
        private string _method { get; set; }
        private bool _useSignTable = true;
        public string Build(Dictionary<string, object> values, string prefix)
        {
            var table = EntityUtil.GetTable<T>();
            var column = ExpressionUtil.BuildColumn(_column, values, prefix).SingleOrDefault().Value;
            var where = ExpressionUtil.BuildExpression(_where, values, prefix, _useSignTable);
            if (_method == nameof(this.Select))
            {
                return string.Format("(select {0} from {1} where {2})", column, table.TableName, where);
            }
            if (_method == nameof(this.Count))
            {
                return string.Format("(select count({0}) from {1} where {2})", column, table.TableName, where);
            }
            throw new NotImplementedException();
        }
        public SubQuery<T> Where(Expression<Func<T, bool>> expression)
        {
            _where = expression;
            return this;
        }
        public SubQuery<T> Where<T1, T2>(Expression<Func<T1, T2, bool>> expression)
        {
            _useSignTable = false;
            _where = expression;
            return this;
        }
        public SubQuery<T> Select<TResut>(Expression<Func<T, TResut>> expression)
        {
            _method = nameof(this.Select);
            _column = expression;
            return this;
        }
        public SubQuery<T> Count<TResut>(Expression<Func<T, TResut>> expression)
        {
            _method = nameof(this.Count);
            _column = expression;
            return this;
        }
    
        public override bool Equals(object obj)
        {
            return obj is SubQuery<T> query &&
                   EqualityComparer<Expression>.Default.Equals(_where, query._where) &&
                   EqualityComparer<Expression>.Default.Equals(_column, query._column) &&
                   _method == query._method;
        }
    
        public override int GetHashCode()
        {
            return HashCode.Combine(_where, _column, _method);
        }
    
        public static bool operator <(object t1, SubQuery<T> t2)
        {
            return false;
        }
        public static bool operator ==(object t1, SubQuery<T> t2)
        {
            return false;
        }
        public static bool operator !=(object t1, SubQuery<T> t2)
        {
            return false;
        }
        public static bool operator <=(object t1, SubQuery<T> t2)
        {
            return false;
        }
        public static bool operator >=(object t1, SubQuery<T> t2)
        {
            return false;
        }
        public static bool operator >(object t1, SubQuery<T> t2)
        {
            return false;
        }
    
        public static explicit operator string(SubQuery<T> v)=> string.Empty;
        
    }
    
    step2: use
    //in where
    var subquery1 = new SubQuery<Student>()
        .Where(a => a.Id <= 15)
        .Select(s => s.Age);
    
    var student1 = context.From<Student>()
        .Where(a=>a.Age>=Operator.Any(subquery1))
        .Select();
    
    //in columns
    var subquery2 = new SubQuery<School>()
       .Where<Student,School>((a,b) => a.SchoolId==b.Id)
       .Select(s => s.Name);
    
    var student2 = context.From<Student>()
        .Select(s=>new
        {
            s.Id,
            StudentName = s.Name,
            SchoolName = (string)subquery2//just for build
        });
  • 相关阅读:
    Redis从0到精通Redis持久化
    Redis从0到精通事务
    Redis从0到精通Nosql概述
    LAMP源码MySQL集群版搭建 枯木
    Apache mod_cband 流量控制 枯木
    MySQL簇概述 枯木
    RHEL6 sysbench libtool error 枯木
    shell脚本不换行刷新数据 枯木
    MySQLCluster 枯木
    MFS部署 枯木
  • 原文地址:https://www.cnblogs.com/chaeyeon/p/11259313.html
Copyright © 2011-2022 走看看