private static void AddDbParameter(IRepositoryHelper repositoryHelper, List <DbParameter> dbParameters, SqlWithParameters sqlParameter) { if (sqlParameter.Parameters != null && sqlParameter.Parameters.Count() > 0) { foreach (var kvParamter in sqlParameter.Parameters) { var dbParameter = repositoryHelper.CreateDbParmeter(kvParamter.Key, kvParamter.Value); dbParameters.Add(dbParameter); } } }
public static IQueryable <TResult> TreeQuery <TEntity, TKey, TResult>(IRepositoryHelper repositoryHelper, IQueryable <TEntity> query, IEntityType entityType, Expression <Func <TEntity, bool> > startQuery, Expression <Func <TEntity, TResult> > selector, Expression <Func <TEntity, bool> > whereQuery = null, bool upSearch = false, string orderByProperty = null, int level = 0, bool distinct = false) where TEntity : class, IEntity <TKey> //ITreeEntity<TKey> where TResult : class //where TKey : struct, IEquatable<TKey> { var tableAnnn = entityType.FindAnnotation("Relational:TableName"); string tableName = tableAnnn?.Value.ToString(); var anno = entityType.FindProperty(nameof(ITreeEntity.Pid)).FindAnnotation("Relational:ColumnName"); string parentFieldName = anno != null?anno.Value.ToString() : nameof(ITreeEntity <int> .Pid); var idAnno = entityType.FindProperty(nameof(ITreeEntity.Id)).FindAnnotation("Relational:ColumnName"); string fieldName = idAnno != null?idAnno.Value.ToString() : nameof(ITreeEntity <int> .Id); List <DbParameter> dbParameters = new List <DbParameter>(); SqlWithParameters firstSqls = query.Where(startQuery).Select(selector).GetSqlTextWithParement();; AddDbParameter(repositoryHelper, dbParameters, firstSqls); string firstQuery = firstSqls.Sql.Replace(Environment.NewLine, " "); string startQueryParament = startQuery.Parameters[0].Name; bool forNpgsql = IsNpgSql(repositoryHelper?.ProviderName); string orderByFieldName = null; if (!string.IsNullOrEmpty(orderByProperty)) { var orderByAnno = entityType.FindProperty(orderByProperty).FindAnnotation("Relational:ColumnName"); orderByFieldName = orderByAnno != null?orderByAnno.Value.ToString() : string.Format("\"{0}\"", orderByProperty); //forNpgsql = repositoryHelper.ProviderName == "Npgsql.EntityFrameworkCore.PostgreSQL"; } if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { firstQuery = firstQuery.Insert(firstQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", 0 As level, array[\"{0}\".\"{1}\"] as sorder", startQueryParament, orderByFieldName)); } else { firstQuery = firstQuery.Insert(firstQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", 0 As level"); } //with recursive mytree as ( //select "t"."id", "t"."createtime", "t"."creator", "t"."customdata", "t"."displayname", "t"."group", "t"."icon", "t"."isenabled", "t"."isvisible", "t"."lastmodifytime", "t"."modifier", "t"."name", "t"."pid", "t"."platsupport", "t"."requiredpermissionname", "t"."requiresauthentication", "t"."sindex", "t"."target", "t"."url", 0 as level, ARRAY[t.sindex] as sorder from "menus" as "t" where "t"."pid" is null //union all //select "tt"."id", "tt"."createtime", "tt"."creator", "tt"."customdata", "tt"."displayname", "tt"."group", "tt"."icon", "tt"."isenabled", "tt"."isvisible", "tt"."lastmodifytime", "tt"."modifier", "tt"."name", "tt"."pid", "tt"."platsupport", "tt"."requiredpermissionname", "tt"."requiresauthentication", "tt"."sindex", "tt"."target", "tt"."url", mytree.level + 1, sorder || tt.sindex as sorder from "menus" as "tt" join mytree on "tt"."pid" = "mytree"."id" where "tt"."group" = 0 //) //select * from "mytree" as "t" where "t"."group" = 0 ORDER BY SORDER string secondQuery = null; string thirdQuery = null; string whereQueryParament = tableName.Substring(0, 1).ToLower(); if (whereQuery == null) { secondQuery = query.Select(selector).ToSql().Replace(Environment.NewLine, " "); whereQueryParament = selector.Parameters[0].Name; thirdQuery = secondQuery; if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", mytree.level + 1, sorder || \"{0}\".\"{1}\" as sorder", whereQueryParament, orderByFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", mytree.level + 1"); } if (upSearch) { secondQuery += string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, fieldName, parentFieldName); } else { secondQuery += string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, parentFieldName, fieldName); } } else { SqlWithParameters secondSqls = secondSqls = query.Where(whereQuery).Select(selector).GetSqlTextWithParement(); AddDbParameter(repositoryHelper, dbParameters, secondSqls); secondQuery = secondSqls.Sql.Replace(Environment.NewLine, " "); thirdQuery = secondQuery; whereQueryParament = whereQuery.Parameters[0].Name; if (whereQueryParament == startQueryParament) { if (forNpgsql) { string forReplace = startQueryParament + "."; whereQueryParament += startQueryParament; string toReplace = whereQueryParament + "."; secondQuery = secondQuery.Replace(forReplace, toReplace); secondQuery = secondQuery.Replace("AS " + startQueryParament, "AS " + whereQueryParament); } else { string forReplace = "\"" + startQueryParament + "\""; whereQueryParament += startQueryParament; string toReplace = "\"" + whereQueryParament + "\""; secondQuery = secondQuery.Replace(forReplace, toReplace); } } if (forNpgsql) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", mytree.level + 1, sorder || \"{0}\".\"{1}\" as sorder", whereQueryParament, orderByFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", mytree.level + 1"); } if (upSearch) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" WHERE", StringComparison.CurrentCultureIgnoreCase), string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, fieldName, parentFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" WHERE", StringComparison.CurrentCultureIgnoreCase), string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, parentFieldName, fieldName)); } } StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.Append("with recursive mytree as ( "); sqlBuilder.Append(firstQuery); sqlBuilder.Append(" union all "); sqlBuilder.Append(secondQuery); if (!forNpgsql) { sqlBuilder.Append(" order by level desc"); if (!string.IsNullOrEmpty(orderByFieldName)) { //var orderByAnno = entityType.FindProperty(orderByProperty).FindAnnotation("Relational:ColumnName"); //string orderByFieldName = orderByAnno!=null? orderByAnno.Value.ToString() : string.Format("\"{0}\"", orderByProperty); sqlBuilder.Append(string.Format(", {0}", orderByFieldName)); } } sqlBuilder.Append(") "); if (distinct) { thirdQuery = thirdQuery.Replace("SELECT", "SELECT DISTINCT"); } thirdQuery = thirdQuery.Replace(tableName, "mytree"); sqlBuilder.Append(thirdQuery); if (level > 0) { if (whereQuery == null) { sqlBuilder.Append(" where "); } else { sqlBuilder.Append(" and "); } sqlBuilder.Append(string.Format("level = {0}", repositoryHelper.CreateParameterName("level"))); AddDbParameter(repositoryHelper, dbParameters, "level", level); } if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { sqlBuilder.Append(" order by sorder"); } //外部where // var pp = db.Database.GetDbConnection().CreateCommand().CreateParameter(); // pp.ParameterName ="tid"; // pp.Value = 1; return(query.Select(selector).FromSql(sqlBuilder.ToString(), dbParameters.ToArray())); }