获得ToTraceString()为IQueryable的(Obtain ToTraceString

2019-10-18 20:51发布

我用

  `.....
   .....
  query = query.Where(criterion, fiedNames);
  string sql2 = ((ObjectQuery)query).ToTraceString();'

获取和调整是要通过LINQ执行SQL代码。

当我快看,我得到了下面的SQL语句,我不明白。

SELECT [UnionAll2].[C3] AS [C1], [UnionAll2].[C4] AS [C2],
[UnionAll2].[C5] AS [C3], [UnionAll2].[C6] AS [C4], 
[UnionAll2].[C7] AS [C5], 
[UnionAll2].[C8] AS [C6], 
[UnionAll2].[C9] AS [C7],  
..... few hundereds line more.....
@p__linq__4 AS [C2], 
.....
CASE 
     WHEN ( [Join5].[id] IS NULL ) THEN 
     Cast(NULL AS INT) 
     WHEN ( @p__linq__0 = 1 )

.......

显然,如果我粘贴到SQL Management Studio并执行它会抛出我的错误,如果我不传递值@p__linq__0 ....

我的问题:如何获得跟踪SQL,可以在SQL管理执行呢?

Answer 1:

   public class LinqProvider<T>
    {
        static readonly FieldInfo INTERNAL_QUERY_FIELD;
        static readonly FieldInfo QUERYSTATE_FIELD;

        static LinqProvider()
        {
            INTERNAL_QUERY_FIELD = typeof(DbQuery<T>).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.Name.Equals("_internalQuery"));
            QUERYSTATE_FIELD = typeof(System.Data.Entity.Core.Objects.ObjectQuery<>).BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == "_state");
        }

        public IQueryable<T> QueryContext { get; set; }

        InternalQuery _InternalQueryContext;
        public InternalQuery InternalQueryContext
        {
            get
            {
                if (_InternalQueryContext == null)
                {
                    _InternalQueryContext = new InternalQuery();

                    if (QueryContext is DbQuery<T>)
                    {
                        var internalQuery = INTERNAL_QUERY_FIELD.GetValue(QueryContext);

                        var objectQueryField = internalQuery.GetType().GetProperties().FirstOrDefault(f => f.Name.Equals("ObjectQuery"));

                        _InternalQueryContext.ObjectQueryContext = objectQueryField.GetValue(internalQuery) as System.Data.Entity.Core.Objects.ObjectQuery<T>;
                    }
                    else if (QueryContext is System.Data.Entity.Core.Objects.ObjectQuery<T>)
                    {
                        _InternalQueryContext.ObjectQueryContext = (QueryContext as System.Data.Entity.Core.Objects.ObjectQuery<T>);
                    }
                }

                return _InternalQueryContext;
            }
        }

        public LinqProvider(IQueryable<T> queryContext)
        {
            QueryContext = queryContext;
        }

        public class InternalQuery
        {
            public System.Data.Entity.Core.Objects.ObjectQuery<T> ObjectQueryContext { get; set; }

            public string ToTraceString(IDictionary<string, object> Parameters = null)
            {
                var state = QUERYSTATE_FIELD.GetValue(ObjectQueryContext);

                var mi = state.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == "GetExecutionPlan");

                mi.Invoke(state, new object[] { null });

                var paramState = state.GetType().BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == "_parameters");

                if (paramState != null)
                {
                    System.Data.Entity.Core.Objects.ObjectParameterCollection col = paramState.GetValue(state) as System.Data.Entity.Core.Objects.ObjectParameterCollection;

                    if (col != null && Parameters != null)
                    {
                        foreach (var item in col)
                        {
                            Parameters.Add(item.Name, item.Value);
                        }
                    }
                }

                return ObjectQueryContext.ToTraceString();
            }
        }
    }


Answer 2:

这个扩展方法,你可以断言:

 /// <summary>
    /// Traces IQueryable's DB query />
    /// </summary>
    /// <typeparam name="TEntity">IQueryable type</typeparam>
    /// <param name="query">The IQueryable query</param>
    /// <returns>Query</returns>
    public static string ToTraceString<TEntity>(this IQueryable<TEntity> query)
    {
        StringBuilder sb = new StringBuilder();

        var objQuery = query as ObjectQuery<TEntity>;
        if (objQuery != null)
        {
            sb.AppendLine();
            if(objQuery.Parameters.Count > 0)
            {
                sb.AppendLine("Query parameters:");
                sb.AppendLine("--------------------------------------------------------------");
                sb.AppendLine("      Name          |        Type        |       Value        ");
                sb.AppendLine("--------------------------------------------------------------");
                foreach (var param in objQuery.Parameters) 
                {
                    sb.AppendFormat("{0, -20}|{1, -20}|{2, -20}{3}", param.Name, param.ParameterType.ToString(), param.Value, Environment.NewLine);
                }
                sb.AppendLine();
            }

            string partialQuery = objQuery.ToTraceString();
            objQuery.Parameters.ToList().ForEach(p => partialQuery = partialQuery.Replace(":" + p.Name, p.Value.ToString()));

            sb.AppendLine(partialQuery);
        }

        // replace 

        return sb.ToString();
    }


Answer 3:

扩展方法名称更改为TraceString2,例如,因为TraceString是相同的ObjectQuery方法名。

这个扩展,显示的查询参数的所有数据(@p_ LINQ _0 ...):

using (var context = new MyEntities(true))
{
    string cpty = "MiCpty";
    DateTime date = DateTime.Today;

    var query = context.CECA_SPECIAL_CAS.Where(a => a.IDACUERDO == cpty 
                                                    && a.FECHAENTRADA == date);
    query.ToList();

    System.Diagnostics.Debug.Print(query.ToTraceString2());
}

结果:

查询参数:

名称| 类型| 值

P_ LINQ _0 | System.String | MiCpty
P_ LINQ _1 | System.DateTime的| 31/10/2013 00:00:00

选择 “Extent1”。 “IDACUERDO” AS “IDACUERDO” “Extent1”。 “NOMBREPRINCIPAL” AS “NOMBREPRINCIPAL” “Extent1”。 “NOMBRELEGAL” AS “NOMBRELEGAL” “Extent1”。 “NOMBRELARGO” AS “NOMBRELARGO”,“ Extent1 “” FECHAENTRADA “AS” FECHAENTRADA “” Extent1 “” DIASEMANAOPERAR “AS” DIASEMANAOPERAR “” Extent1 “” 契约式 “AS” 契约式 “” Extent1 “” 频率 “AS” 频率 “” Extent1“ “DESC_PERIODICIDAD” AS “DESC_PERIODICIDAD” “Extent1”。 “ON”, “ON”, “Extent1。” AS “MA_TYPE” AS “MA_TYPE” “Extent1”。 “MA_VERSION” AS “MA_VERSION” “Extent1”。“ COLLATERALPORTFOLIOCODE “AS” COLLATERALPORTFOLIOCODE “FROM” CKCOL_ADM “” CECA_SPECIAL_CA “” Extent1 “WHERE((” Extent1 “” IDACUERDO “= MiCpty)AND(” Extent1 “” FECHAENTRADA“31/10/2013 00:00:00 = ))



Answer 4:

您可以看到与SQL Server 2008中的工具“SQL Server设置”执行的查询。



文章来源: Obtain ToTraceString() for IQueryable