You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
//"LinqTypeMap" file in unit test project Dapper.SqlMapper.TypeMapProvider=(type)=>newLinqTypeMap(type);DbContextFactory.AddDataSource(newDataSource(){Default=true,Name="mysql",ConnectionFacotry=()=>newMySql.Data.MySqlClient.MySqlConnection("server=localhost;user id=root;password=1024;database=test;"),DatasourceType=DatasourceType.MYSQL,UseProxy=true//use static proxy,for logger});
Insert
IDbContextcontext=null;try{context=DbContextFactory.GetDbContext();//because set "id[isIdentity=true]",so not set "id" valuevarrow1=context.From<Student>().Insert(newStudent(){Grade=Grade.A,CreateTime=DateTime.Now,Name="jack",});//batch addedvarrow2=context.From<Student>().Insert(newList<Student>(){newStudent(){Grade=Grade.C,CreateTime=DateTime.Now,Name="tom",},newStudent(){Grade=Grade.F,CreateTime=DateTime.Now,Name="jar",},});}catch(Exceptione){//debug sql loggerConsole.WriteLine(context.Loggers);}finally{context.Close();}
Update
using(varcontext=DbContextFactory.GetDbContext()){//paramvarage=20;DateTime?time=null;varsid=1;//subqueryvarsubquery=newSubQuery<School>().Where(a =>a.Id==sid).Select(s =>s.Name);varrow1=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();//functioncontext.From<Student>().Set(a =>a.Name, a =>MysqlFun.REPLACE(a.Name,"a","b")).Where(a =>a.Id==14).Update();//lockvarstudent=context.From<Student>().Where(a =>a.Id==16).Single();varrow2=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 update by primary keyvarrow3=context.From<Student>().Filter(a =>a.SchoolId).Update(newStudent(){Id=2,CreateTime=DateTime.Now});//reset update wherevarrow3=context.From<Student>().Where(a =>a.Id=2&&a.Version=oldVersion).Update(newStudent(){Id=2,Version=Guid.NewGuid().ToString(),CreateTime=DateTime.Now});
IDbContextdbContext=null;try{dbContext=DbContextFactory.GetDbContext();dbContext.Open(true);dbContext.From<Student>().Insert(newStudent(){Name="stduent1"});//throw new Exception("rollback");dbContext.From<School>().Insert(newSchool(){Name="school1"});dbContext.Commit();}catch(Exception){dbContext?.Rollback();throw;}finally{dbContext?.Close();}
Anonymous
// Custom Mapper Handles the Problem that Anonymous Types Can't Match Constructors//Copy "DefaultTypeMap" from "dapper" and modify this methodpublicConstructorInfoFindConstructor(string[]names,Type[]types){varconstructors=_type.GetConstructors(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);foreach(ConstructorInfoctorinconstructors.OrderBy(c =>c.IsPublic?0:(c.IsPrivate?2:1)).ThenBy(c =>c.GetParameters().Length)){ParameterInfo[]ctorParameters=ctor.GetParameters();if(ctorParameters.Length==0)returnctor;if(ctorParameters.Length!=types.Length)continue;inti=0;for(;i<ctorParameters.Length;i++){if(!string.Equals(ctorParameters[i].Name,names[i],StringComparison.OrdinalIgnoreCase))break;if(types[i]==typeof(byte[])&&ctorParameters[i].ParameterType.FullName=="System.Data.Linq.Binary")continue;varunboxedType=Nullable.GetUnderlyingType(ctorParameters[i].ParameterType)??ctorParameters[i].ParameterType;//if ((unboxedType != types[i] && !SqlMapper.HasTypeHandler(unboxedType))// && !(unboxedType.IsEnum && Enum.GetUnderlyingType(unboxedType) == types[i])// && !(unboxedType == typeof(char) && types[i] == typeof(string))// && !(unboxedType.IsEnum && types[i] == typeof(string)))//{// break;//}}if(i==ctorParameters.Length)returnctor;}returnnull;}SqlMapper.TypeMapProvider=(type)=>newLinqTypeMap();
Select
//singlevarstudent=context.From<Student>().Where(a =>a.Id==19).Single();//subqueryvarid=0;varage=50;varsubquery=newSubQuery<School>().Where(a =>a.Id>=id).Select(a =>a.Id);//Verify that subquery parameters are written to the current queryvarstudents2=context.From<Student>().OrderBy(a =>a.Age).Where(a =>a.Id>=Operator.Any(subquery)&&a.Age>age).Select();//Partial columnsvarstudents3=context.From<Student>().Select(s =>new{s.Id,s.Age});
//limit 0,10varstudents1=context.From<Student>().Take(10).Select();//limit 10,20 varstudents2=context.From<Student>().Skip(10,20).Select();//Calling functions in expressions is not recommended, but n-tier attribute access is supportedvarstudent3=context.From<Student>().Where(a =>a.CreateTime==DateTime.Now.Date).Select();//lockvarstudents4=context.From<Student>().With(LockType.FOR_UPADTE).Select();//exists1varflag1=context.From<Student>().Where(a =>a.Id>50).Exists();//exists2varsubquery=newSubQuery<School>().Where(a =>a.Id>=2).Select(a =>a.Id);varflag2=context.From<Student>().Where(a =>Operator.Exists(subquery)).Count();//countvarcount=context.From<Student>().Where(a =>a.Id>50).Count();//sumvarsum=context.From<Student>().Where(a =>a.Id>50).Sum(s =>s.Id*s.Age);//distinctvardisinct=context.From<Student>().Distinct().Select(s =>s.Name);
varprefix="@";varvalues=newDictionary<string,object>();Expression<Func<Student,bool>>expression= s =>s.Age>40;varexpression=ExpressionUtil.BuildExpression(expression,values,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.publicclassCase<T>:ISqlBuilder{privateList<Expression>_whens=newList<Expression>();privateList<string>_thens=newList<string>();string_else=null;publicstringBuild(Dictionary<string,object>values,stringprefix){varsb=newStringBuilder();foreach(varitemin_whens){varexpress=ExpressionUtil.BuildExpression(item,values,prefix);sb.AppendFormat(" WHEN {0} THEN '{1}'",express,_thens[_whens.IndexOf(item)]);}if(_else!=null){sb.AppendFormat(" ELSE '{0}'",_else);}returnstring.Format("(CASE {0} END)",sb);}publicstaticimplicitoperatorstring(Case<T>d)=>string.Empty;publicCase<T>When(Expression<Func<T,bool>>expression){newDictionary<string,object>();_whens.Add(expression);returnthis;}publicCase<T>Then(stringvalue){_thens.Add(value);returnthis;}publicCase<T>Else(stringvalue){_else=value;returnthis;}}
step2: use
//casevarcaseWhen=newCase<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 instancevarstudents1=context.From<Student>().Where(a =>caseWhen=="Old"||caseWhen=="Youth").Select(s =>new{s.Id,GroupAge=(string)caseWhen});
varadddayfun=newDateAdd<Student>(a =>a.CreateTime,1,"day");//in columusvarstudent1=context.From<Student>().Select(s =>new{s.Id,DateTime=(DateTime)adddayfun//just for type inference});//in expressionvarstudent2=context.From<Student>().Where(a =>adddayfun>DateTime.Now).Select();
DEMO.3 Window Function
step1: implement
publicclassWinFun<T>:ISqlBuilder{string_partition{get;set;}string_orderby{get;set;}privatestring_methodName{get;set;}publicWinFun<T>ROW_NUMBER(){_methodName=nameof(ROW_NUMBER);returnthis;}publicWinFun<T>PARTITION<TResult>(Expression<Func<T,TResult>>columns){varcls=ExpressionUtil.BuildColumns(columns,null,null);_partition+=string.Join(",",cls.Select(s =>s.Value));returnthis;}publicWinFun<T>ORDERBY<TResult>(Expression<Func<T,TResult>>columns,boolasc=true){varcls=ExpressionUtil.BuildColumns(columns,null,null);_orderby+=string.Join(",",cls.Select(s =>s.Value));_orderby+=!asc?"DESC":"ASC";returnthis;}/*If there are no parameters in the expression, there is no need to build in build-method*/publicstringBuild(Dictionary<string,object>values,stringprefix){if(_methodName==nameof(ROW_NUMBER)){returnstring.Format("ROW_NUMBER()OVER(ORDER BY {0})",_orderby);}thrownewNotImplementedException();}publicstaticimplicitoperatorulong(WinFun<T>d)=>0;}
publicclassSubQuery<T>:ISubQuerywhereT:class{privateExpression_where{get;set;}privateExpression_column{get;set;}privatestring_method{get;set;}privatebool_useSignTable=true;publicstringBuild(Dictionary<string,object>values,stringprefix){vartable=EntityUtil.GetTable<T>();varcolumn=ExpressionUtil.BuildColumn(_column,values,prefix).SingleOrDefault().Value;varwhere=ExpressionUtil.BuildExpression(_where,values,prefix,_useSignTable);if(_method==nameof(this.Select)){returnstring.Format("(select {0} from {1} where {2})",column,table.TableName,where);}if(_method==nameof(this.Count)){returnstring.Format("(select count({0}) from {1} where {2})",column,table.TableName,where);}thrownewNotImplementedException();}publicSubQuery<T>Where(Expression<Func<T,bool>>expression){_where=expression;returnthis;}publicSubQuery<T>Where<T1,T2>(Expression<Func<T1,T2,bool>>expression){_useSignTable=false;_where=expression;returnthis;}publicSubQuery<T>Select<TResut>(Expression<Func<T,TResut>>expression){_method=nameof(this.Select);_column=expression;returnthis;}publicSubQuery<T>Count<TResut>(Expression<Func<T,TResut>>expression){_method=nameof(this.Count);_column=expression;returnthis;}publicoverrideboolEquals(objectobj){returnobjisSubQuery<T>query&&EqualityComparer<Expression>.Default.Equals(_where,query._where)&&EqualityComparer<Expression>.Default.Equals(_column,query._column)&&_method==query._method;}publicoverrideintGetHashCode(){returnHashCode.Combine(_where,_column,_method);}publicstaticbooloperator<(objectt1,SubQuery<T>t2){returnfalse;}publicstaticbooloperator==(objectt1,SubQuery<T>t2){returnfalse;}publicstaticbooloperator!=(objectt1,SubQuery<T>t2){returnfalse;}publicstaticbooloperator<=(objectt1,SubQuery<T>t2){returnfalse;}publicstaticbooloperator>=(objectt1,SubQuery<T>t2){returnfalse;}publicstaticbooloperator>(objectt1,SubQuery<T>t2){returnfalse;}publicstaticexplicitoperatorstring(SubQuery<T>v)=>string.Empty;}
step2: use
//in wherevarsubquery1=newSubQuery<Student>().Where(a =>a.Id<=15).Select(s =>s.Age);varstudent1=context.From<Student>().Where(a=>a.Age>=Operator.Any(subquery1)).Select();//in columnsvarsubquery2=newSubQuery<School>().Where<Student,School>((a,b)=>a.SchoolId==b.Id).Select(s =>s.Name);varstudent2=context.From<Student>().Select(s=>new{s.Id,StudentName=s.Name,SchoolName=(string)subquery2//just for build});