diff --git a/Src/Asp.Net/SqlServerTest/Demo/Demo1_Queryable.cs b/Src/Asp.Net/SqlServerTest/Demo/Demo1_Queryable.cs index 0bc167e37..1ab2ac666 100644 --- a/Src/Asp.Net/SqlServerTest/Demo/Demo1_Queryable.cs +++ b/Src/Asp.Net/SqlServerTest/Demo/Demo1_Queryable.cs @@ -15,6 +15,32 @@ namespace OrmTest JoinTable(); Async(); NoEntity(); + Mapper(); + } + + private static void Mapper() + { + Console.WriteLine(""); + Console.WriteLine("#### Mapper Start ####"); + var db = GetInstance(); + //Creater Table + db.CodeFirst.InitTables(typeof(Tree)); + db.DbMaintenance.TruncateTable("tree"); + db.Insertable(new Tree() { Id = 1, Name = "root" }).ExecuteCommand(); + db.Insertable(new Tree() { Id = 11, Name = "child1",ParentId=1 }).ExecuteCommand(); + db.Insertable(new Tree() { Id = 12, Name = "child2",ParentId=1 }).ExecuteCommand(); + db.Insertable(new Tree() { Id = 2, Name = "root" }).ExecuteCommand(); + db.Insertable(new Tree() { Id = 22, Name = "child3", ParentId = 2 }).ExecuteCommand(); + + var list=db.Queryable() + //parent=(select * from parent where id=it.parent) + .Mapper(it=>it.Parent,it=>it.ParentId, it=>it.Parent.Id) + //Child=(select * from parent where ParentId=it.id) + .Mapper(it => it.Child, it => it.Id, it => it.Parent.ParentId) + .ToList(); + + + Console.WriteLine("#### End Start ####"); } private static void NoEntity() diff --git a/Src/Asp.Net/SqlServerTest/Models/Mappers.cs b/Src/Asp.Net/SqlServerTest/Models/Mappers.cs new file mode 100644 index 000000000..d2878de64 --- /dev/null +++ b/Src/Asp.Net/SqlServerTest/Models/Mappers.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OrmTest +{ + public class Tree + { + [SqlSugar.SugarColumn(IsPrimaryKey =true)] + public int Id { get; set; } + public string Name { get; set; } + public int ParentId { get; set; } + [SqlSugar.SugarColumn(IsIgnore = true)] + public Tree Parent { get; set; } + [SqlSugar.SugarColumn(IsIgnore = true)] + public List Child { get; set; } + } +} diff --git a/Src/Asp.Net/SqlServerTest/SqlServerTest.csproj b/Src/Asp.Net/SqlServerTest/SqlServerTest.csproj index 3e830cfc5..6e483e9d2 100644 --- a/Src/Asp.Net/SqlServerTest/SqlServerTest.csproj +++ b/Src/Asp.Net/SqlServerTest/SqlServerTest.csproj @@ -56,6 +56,7 @@ + diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs index 3a49ba00d..5c38c71fb 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs @@ -93,6 +93,14 @@ namespace SqlSugar this.MapperActionWithCache = mapperAction; return this; } + public ISugarQueryable Mapper(Expression> mapperObject, Expression> mainField, Expression> childField) + { + return _Mapper(mapperObject,mainField,childField); + } + public ISugarQueryable Mapper(Expression>> mapperObject, Expression> mainField, Expression> childField) + { + return _Mapper(mapperObject, mainField, childField); + } public virtual ISugarQueryable Mapper(Expression>> mapperObject, Expression> mapperField) { return _Mapper(mapperObject, mapperField); @@ -1334,6 +1342,168 @@ namespace SqlSugar return this; } + private ISugarQueryable _Mapper(Expression mapperObject, Expression mainField, Expression childField) + { + if ((mapperObject as LambdaExpression).Body is UnaryExpression) + { + mapperObject = ((mapperObject as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mapperObject = (mapperObject as LambdaExpression).Body; + } + if ((mainField as LambdaExpression).Body is UnaryExpression) + { + mainField = ((mainField as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mainField = (mainField as LambdaExpression).Body; + } + if ((childField as LambdaExpression).Body is UnaryExpression) + { + childField = ((childField as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + childField = (childField as LambdaExpression).Body; + } + Check.Exception(mapperObject is MemberExpression == false || mainField is MemberExpression == false, ".Mapper() parameter error"); + var mapperObjectExp = mapperObject as MemberExpression; + var mainFieldExp = mainField as MemberExpression; + var childFieldExp = childField as MemberExpression; + Check.Exception(mainFieldExp.Type.IsClass(), ".Mapper() parameter error"); + Check.Exception(childFieldExp.Type.IsClass(), ".Mapper() parameter error"); + var objType = mapperObjectExp.Type; + var filedType = mainFieldExp.Expression.Type; + Check.Exception(objType != typeof(TObject) && objType != typeof(List), ".Mapper() parameter error"); + if (objType == typeof(List)) + { + objType = typeof(TObject); + } + var mainFiledName = mainFieldExp.Member.Name; + var childFiledName = childFieldExp.Member.Name; + var objName = mapperObjectExp.Member.Name; + var filedEntity = this.Context.EntityMaintenance.GetEntityInfo(objType); + var objEntity = this.Context.EntityMaintenance.GetEntityInfo(filedType); + var isSelf = filedType == typeof(T); + if (Mappers == null) + Mappers = new List>>(); + if (isSelf) + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty() || !entitys.Any()) return; + var entity = entitys.First(); + var whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(childFiledName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(mainFiledName).GetValue(it, null).ObjToString()).ToList(); + List wheres = new List() + { + new ConditionalModel() + { + FieldName=whereCol.DbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues.Distinct()) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(mainFiledName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(whereCol.PropertyName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + else + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty() || !entitys.Any()) return; + var entity = entitys.First(); + var tEntity = this.Context.EntityMaintenance.GetEntityInfo(); + var whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(childFiledName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(whereCol.PropertyName).GetValue(it, null).ObjToString()).ToList(); + var dbColumnName = filedEntity.Columns.FirstOrDefault(it => it.PropertyName == mainFiledName).DbColumnName; + List wheres = new List() + { + new ConditionalModel() + { + FieldName=dbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(whereCol.PropertyName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(mainFiledName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + + return this; + } protected int GetCount() { var sql = string.Empty; diff --git a/Src/Asp.Net/SqlSugar/Interface/IQueryable.cs b/Src/Asp.Net/SqlSugar/Interface/IQueryable.cs index fedb02c56..35f64c7df 100644 --- a/Src/Asp.Net/SqlSugar/Interface/IQueryable.cs +++ b/Src/Asp.Net/SqlSugar/Interface/IQueryable.cs @@ -21,6 +21,8 @@ namespace SqlSugar ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); ISugarQueryable Mapper(Action mapperAction); ISugarQueryable Mapper(Action> mapperAction); + ISugarQueryable Mapper(Expression> mapperObject, Expression> mainField, Expression> childField); + ISugarQueryable Mapper(Expression>> mapperObject, Expression> mainField, Expression> childField); ISugarQueryable Mapper(Expression> mapperObject, Expression> mapperField); ISugarQueryable Mapper(Expression>> mapperObject, Expression> mapperField); ISugarQueryable AddParameters(object parameters);