1

私が使う

  `.....
   .....
  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管理スタジオに貼り付けて実行すると、値を渡さないとエラーが発生し@p__linq__0ます....

私の質問: SQL 管理で実行できるトレース SQL を取得するにはどうすればよいですか?

4

4 に答える 4

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();
            }
        }
    }
于 2014-06-24T15:21:44.583 に答える
0

実行されたクエリは、SQL Server 2008 ツールの「Sql Server Profiler」で確認できます。

于 2013-10-31T10:03:20.377 に答える
0

たとえば、TraceString は同じ ObjectQuery メソッド名であるため、拡張メソッド名を TraceString2 に変更します。

この拡張機能は、クエリ パラメータ (@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

SELECT "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"."TIPOCONTRATO" AS "TIPOCONTRATO", "Extent1"."PERIODICIDAD" AS "PERIODICIDAD", "Extent1" ."DESC_PERIODICIDAD" AS "DESC_PERIODICIDAD", "Extent1"."ACTIVO" AS "ACTIVO", "Extent1"."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 " = 2013 年 10 月 31 日 00:00:00))

于 2013-10-31T07:41:42.520 に答える