328 lines
15 KiB
C#
328 lines
15 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
|
||
namespace SqlSugar
|
||
{
|
||
public class MapperExpressionResolve
|
||
{
|
||
private Expression expression;
|
||
private List<MapperExpression> mappers;
|
||
private InvalidOperationException ex;
|
||
private SqlSugarProvider context;
|
||
private QueryBuilder querybuiler;
|
||
private ISqlBuilder sqlBuilder;
|
||
private string sql;
|
||
public MapperExpressionResolve(Expression expression, InvalidOperationException ex)
|
||
{
|
||
this.expression = expression;
|
||
this.ex = ex;
|
||
this.mappers = CallContext.MapperExpression.Value;
|
||
Error01();
|
||
var isMember = expression is MemberExpression;
|
||
if (isMember)
|
||
{
|
||
ResolveMember();
|
||
}
|
||
else
|
||
{
|
||
ResolveList();
|
||
}
|
||
}
|
||
|
||
private void ResolveList()
|
||
{
|
||
var methodExpression = expression as MethodCallExpression;
|
||
var callName = methodExpression.Method.Name;
|
||
var exp = methodExpression.Arguments[0] as MemberExpression;
|
||
ThrowTrue(exp == null);
|
||
var childExpression = exp;
|
||
MapperExpression mapper = GetMapperMany(exp);
|
||
var fillInfo = GetFillInfoMany(childExpression, mapper);
|
||
var mappingFild1Info = GetMappingFild1ManyInfo(childExpression, mapper);
|
||
var mappingFild1Info2 = GetMappingFild2Info(childExpression, mapper);
|
||
//var SelectInfo = GetSelectInfo(expression);
|
||
this.context.InitMappingInfo(childExpression.Expression.Type);
|
||
var entity = this.context.EntityMaintenance.GetEntityInfo(childExpression.Expression.Type);
|
||
oneToMany(methodExpression, callName, entity, childExpression.Expression.ToString(), fillInfo, mappingFild1Info, mappingFild1Info2);
|
||
}
|
||
|
||
private void ResolveMember()
|
||
{
|
||
var exp = expression as MemberExpression;
|
||
ThrowTrue(exp.Expression == null);
|
||
var childExpression = exp.Expression;
|
||
MapperExpression mapper = GetMapper(exp);
|
||
var fillInfo = GetFillInfo(childExpression, mapper);
|
||
var mappingFild1Info = GetMappingFild1Info(childExpression, mapper);
|
||
var mappingFild1Info2 = GetMappingFild2Info(childExpression, mapper);
|
||
var SelectInfo = GetSelectInfo(expression);
|
||
var entity = this.context.EntityMaintenance.GetEntityInfo(childExpression.Type);
|
||
|
||
var isExMapper = mappingFild1Info2 != null;
|
||
var isFillFild1SameType = fillInfo.Type == mappingFild1Info.Type;
|
||
var isSameProperty = false;
|
||
|
||
if (isExMapper)
|
||
{
|
||
ExtMapper(fillInfo, mappingFild1Info, mappingFild1Info2, SelectInfo);
|
||
}
|
||
else if (isSameProperty)
|
||
{
|
||
|
||
}
|
||
else if (isFillFild1SameType)
|
||
{
|
||
throw new NotSupportedException(expression.ToString());
|
||
}
|
||
else
|
||
{
|
||
oneToOne(fillInfo, mappingFild1Info, mappingFild1Info2, SelectInfo);
|
||
}
|
||
}
|
||
|
||
|
||
private void oneToOne(MapperExpressionInfo fillInfo, MapperExpressionInfo mappingFild1Info, MapperExpressionInfo mappingFild1Info2, MapperExpressionInfo selectInfo)
|
||
{
|
||
var pkColumn = selectInfo.EntityInfo.Columns.Where(it => it.IsPrimarykey == true).FirstOrDefault();
|
||
if (pkColumn == null)
|
||
{
|
||
pkColumn = selectInfo.EntityInfo.Columns.First();
|
||
}
|
||
var tableName = sqlBuilder.GetTranslationTableName(fillInfo.EntityInfo.DbTableName);
|
||
var whereLeft = sqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName);
|
||
var whereRight = sqlBuilder.GetTranslationColumnName(mappingFild1Info.FieldString);
|
||
this.sql = this.context.Queryable<object>()
|
||
.AS(tableName)
|
||
.Where(string.Format(" {0}={1} ", whereLeft, whereRight))
|
||
.Select(sqlBuilder.GetTranslationColumnName(selectInfo.FieldName)).ToSql().Key;
|
||
}
|
||
|
||
private void oneToMany(MethodCallExpression methodCallExpression, string methodName, EntityInfo mainEntity, string shortName, MapperExpressionInfo fillInfo, MapperExpressionInfo mappingFild1Info, MapperExpressionInfo mappingFild1Info2)
|
||
{
|
||
var pkColumn = mainEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true);
|
||
if (pkColumn == null)
|
||
{
|
||
pkColumn = mainEntity.Columns.FirstOrDefault();
|
||
}
|
||
var tableName = sqlBuilder.GetTranslationTableName(fillInfo.EntityInfo.DbTableName);
|
||
var whereLeft = sqlBuilder.GetTranslationColumnName(mappingFild1Info.FieldString);
|
||
var whereRight = sqlBuilder.GetTranslationColumnName(shortName + "." + pkColumn.DbColumnName);
|
||
string whereExpression = GetWhereExpression(methodCallExpression);
|
||
if (methodName == "Any")
|
||
{
|
||
this.sql = " (" + this.context.Queryable<object>()
|
||
.AS(tableName)
|
||
.Where(string.Format(" {0}={1} ", whereLeft, whereRight))
|
||
.WhereIF(!string.IsNullOrEmpty(whereExpression), whereExpression)
|
||
.Select("COUNT(1)").ToSql().Key + ")>0 ";
|
||
}
|
||
else
|
||
{
|
||
this.sql = this.context.Queryable<object>()
|
||
.AS(tableName)
|
||
.Where(string.Format(" {0}={1} ", whereLeft, whereRight))
|
||
.WhereIF(!string.IsNullOrEmpty(whereExpression), whereExpression)
|
||
.Select("COUNT(1)").ToSql().Key;
|
||
}
|
||
}
|
||
|
||
private string GetWhereExpression(MethodCallExpression methodCallExpression)
|
||
{
|
||
if (methodCallExpression.Arguments.Count <= 1)
|
||
return null;
|
||
var exp = methodCallExpression.Arguments[1];
|
||
var querybuiler = InstanceFactory.GetQueryBuilder(this.context.CurrentConnectionConfig);
|
||
querybuiler.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.context.CurrentConnectionConfig);
|
||
querybuiler.Builder = InstanceFactory.GetSqlbuilder(this.context.CurrentConnectionConfig);
|
||
querybuiler.Builder.Context = querybuiler.Context;
|
||
querybuiler.Builder.QueryBuilder = querybuiler;
|
||
querybuiler.Context = this.context;
|
||
var expValue = querybuiler.GetExpressionValue(exp, ResolveExpressType.WhereMultiple);
|
||
var paramterName = (exp as LambdaExpression).Parameters[0].Name;
|
||
var sql = expValue.GetResultString();
|
||
sql = sql.Replace(querybuiler.Builder.GetTranslationColumnName(paramterName) + ".", "");
|
||
if (querybuiler.Parameters != null && querybuiler.Parameters.Count > 0)
|
||
{
|
||
foreach (var item in querybuiler.Parameters)
|
||
{
|
||
sql = sql.Replace(item.ParameterName, item.Value.ObjToString().ToSqlValue());
|
||
}
|
||
}
|
||
return sql;
|
||
}
|
||
|
||
private MapperExpressionInfo GetSelectInfo(Expression expression)
|
||
{
|
||
|
||
var field = expression;
|
||
if (field is UnaryExpression)
|
||
{
|
||
field = (field as UnaryExpression).Operand;
|
||
}
|
||
var type = ((field as MemberExpression).Expression).Type;
|
||
this.context.InitMappingInfo(type);
|
||
var name = (field as MemberExpression).Member.Name;
|
||
var entity = this.context.EntityMaintenance.GetEntityInfo(type);
|
||
var fieldName = entity.Columns.First(it => it.PropertyName == name).DbColumnName;
|
||
return new MapperExpressionInfo()
|
||
{
|
||
Type = type,
|
||
FieldName = fieldName,
|
||
EntityInfo = entity
|
||
};
|
||
}
|
||
|
||
private MapperExpressionInfo GetMappingFild2Info(Expression childExpression, MapperExpression mapper)
|
||
{
|
||
if (mapper.MappingField2Expression == null)
|
||
return null;
|
||
var exp = mapper.MappingField2Expression;
|
||
var field = (exp as LambdaExpression).Body;
|
||
if (field is UnaryExpression)
|
||
{
|
||
field = (field as UnaryExpression).Operand;
|
||
}
|
||
var type = ((field as MemberExpression).Expression).Type;
|
||
this.context.InitMappingInfo(type);
|
||
var name = (field as MemberExpression).Member.Name;
|
||
var entity = this.context.EntityMaintenance.GetEntityInfo(type);
|
||
var fieldName = entity.Columns.First(it => it.PropertyName == name).DbColumnName;
|
||
return new MapperExpressionInfo()
|
||
{
|
||
Type = type,
|
||
FieldName = fieldName
|
||
};
|
||
}
|
||
|
||
private MapperExpressionInfo GetMappingFild1Info(Expression childExpression, MapperExpression mapper)
|
||
{
|
||
var exp = mapper.MappingField1Expression;
|
||
var field = (exp as LambdaExpression).Body;
|
||
if (field is UnaryExpression)
|
||
{
|
||
field = (field as UnaryExpression).Operand;
|
||
}
|
||
var type = ((field as MemberExpression).Expression).Type;
|
||
this.context.InitMappingInfo(type);
|
||
var name = (field as MemberExpression).Member.Name;
|
||
var entity = this.context.EntityMaintenance.GetEntityInfo(type);
|
||
var fieldName = entity.Columns.First(it => it.PropertyName == name).DbColumnName;
|
||
var array = (field as MemberExpression).ToString().Split('.').ToList();
|
||
array[array.Count() - 1] = fieldName;
|
||
var filedString = string.Join(".", array);
|
||
return new MapperExpressionInfo()
|
||
{
|
||
Type = type,
|
||
FieldName = fieldName,
|
||
FieldString = filedString,
|
||
EntityInfo = entity
|
||
};
|
||
}
|
||
|
||
private MapperExpressionInfo GetFillInfo(Expression childExpression, MapperExpression mapper)
|
||
{
|
||
this.querybuiler = mapper.QueryBuilder;
|
||
this.context = mapper.Context;
|
||
this.sqlBuilder = mapper.SqlBuilder;
|
||
if (this.querybuiler.TableShortName.IsNullOrEmpty())
|
||
{
|
||
this.querybuiler.TableShortName = (childExpression as MemberExpression).Expression.ToString();
|
||
}
|
||
this.context.InitMappingInfo(childExpression.Type);
|
||
return new MapperExpressionInfo()
|
||
{
|
||
EntityInfo = this.context.EntityMaintenance.GetEntityInfo(childExpression.Type)
|
||
};
|
||
}
|
||
|
||
private MapperExpression GetMapper(MemberExpression exp)
|
||
{
|
||
var mapper = mappers.Where(it => it.Type == MapperExpressionType.oneToOne)
|
||
.Reverse()
|
||
.Where(it => (it.FillExpression as LambdaExpression).Body.ToString() == exp.Expression.ToString()).FirstOrDefault();
|
||
ThrowTrue(mapper == null);
|
||
return mapper;
|
||
}
|
||
|
||
public string GetMemberName(MemberExpression memberExpression)
|
||
{
|
||
return "";
|
||
}
|
||
|
||
private void ExtMapper(MapperExpressionInfo fillInfo, MapperExpressionInfo mappingFild1Info, MapperExpressionInfo mappingFild1Info2, MapperExpressionInfo selectInfo)
|
||
{
|
||
var tableName = sqlBuilder.GetTranslationTableName(fillInfo.EntityInfo.DbTableName);
|
||
var whereLeft = sqlBuilder.GetTranslationColumnName(mappingFild1Info2.FieldName);
|
||
var whereRight = sqlBuilder.GetTranslationColumnName(mappingFild1Info.FieldString);
|
||
this.sql = this.context.Queryable<object>()
|
||
.AS(tableName)
|
||
.Where(string.Format(" {0}={1} ", whereLeft, whereRight))
|
||
.Select(sqlBuilder.GetTranslationColumnName(selectInfo.FieldName)).ToSql().Key;
|
||
}
|
||
|
||
public MapperSql GetSql()
|
||
{
|
||
return new MapperSql() { Sql = " (" + this.sql + ") " };
|
||
}
|
||
|
||
private MapperExpression GetMapperMany(MemberExpression exp)
|
||
{
|
||
var mapper = mappers.Where(it => it.Type == MapperExpressionType.oneToN)
|
||
.Reverse()
|
||
.Where(it => (it.FillExpression as LambdaExpression).Body.ToString() == exp.ToString()).FirstOrDefault();
|
||
ThrowTrue(mapper == null);
|
||
return mapper;
|
||
}
|
||
private MapperExpressionInfo GetFillInfoMany(Expression childExpression, MapperExpression mapper)
|
||
{
|
||
this.querybuiler = mapper.QueryBuilder;
|
||
this.context = mapper.Context;
|
||
this.sqlBuilder = mapper.SqlBuilder;
|
||
if (this.querybuiler.TableShortName.IsNullOrEmpty())
|
||
{
|
||
this.querybuiler.TableShortName = (childExpression as MemberExpression).Expression.ToString();
|
||
}
|
||
var type = (childExpression as MemberExpression).Type.GetGenericArguments()[0];
|
||
this.context.InitMappingInfo(type);
|
||
return new MapperExpressionInfo()
|
||
{
|
||
EntityInfo = this.context.EntityMaintenance.GetEntityInfo(type)
|
||
};
|
||
}
|
||
private MapperExpressionInfo GetMappingFild1ManyInfo(Expression childExpression, MapperExpression mapper)
|
||
{
|
||
var exp = mapper.MappingField1Expression;
|
||
var field = (exp as LambdaExpression).Body;
|
||
if (field is UnaryExpression)
|
||
{
|
||
field = (field as UnaryExpression).Operand;
|
||
}
|
||
var type = ((field as MemberExpression).Expression).Type;
|
||
this.context.InitMappingInfo(type);
|
||
var name = (field as MemberExpression).Member.Name;
|
||
var entity = this.context.EntityMaintenance.GetEntityInfo(type);
|
||
var fieldName = entity.Columns.First(it => it.PropertyName == name).DbColumnName;
|
||
//var array = (field as MemberExpression).ToString().Split('.').ToList();
|
||
//array[array.Count() - 1] = fieldName;
|
||
//var filedString = string.Join(".", array);
|
||
return new MapperExpressionInfo()
|
||
{
|
||
Type = type,
|
||
FieldName = fieldName,
|
||
FieldString = fieldName,
|
||
EntityInfo = entity
|
||
};
|
||
}
|
||
|
||
void Error01()
|
||
{
|
||
Check.Exception(mappers == null, ErrorMessage.GetThrowMessage(expression.ToString() + "no support Check if the navigation is configured correctly or Includes() is missing", "当前表达式" + expression.ToString() + " 不支持,查看导航是否配置正确等或者缺少Includes() "));
|
||
}
|
||
void ThrowTrue(bool isError)
|
||
{
|
||
Check.Exception(isError, ErrorMessage.GetThrowMessage(expression.ToString() + "no support Check if the navigation is configured correctly or Includes() is missing", "不支持表达式" + expression.ToString() + " ,查看导航是否配置正确等或者缺少Includes() "));
|
||
}
|
||
}
|
||
} |