【问题标题】:See SQL From EntityFramework with Collection-like Queries请参阅 EntityFramework 中的 SQL 以及类似集合的查询
【发布时间】:2010-08-31 07:34:49
【问题描述】:

我没有“完整”版本的 MS SQL (SQL Express 2008),所以我没有分析器工具。

我想查看我的实体框架代码生成的 SQL,但我找到的所有示例都使用了

var x = from u in table
        select u;

语法类型;但我的大多数查询更像是..

var x = context.Users.Single(n => n.Name == "Steven");

语法类型。我可以做些什么来查看从这种编码方式生成的 SQL?有什么想法吗?

【问题讨论】:

标签: sql entity-framework-4


【解决方案1】:

看看这个link...它有一个 EF4 的跟踪提供程序。

我将尝试根据我在单元测试中的使用方式给出一个示例。

第 1 步:注册提供者

有几种方法可以配置提供程序。对于我的单元测试,我通过调用静态方法 RegisterProvider();

在代码中配置了提供程序
[AssemblyInitialize()]
public static void AssemblyInit(TestContext context) {
    EFTracingProviderConfiguration.RegisterProvider();
}

第 2 步:创建实体模型的子类以提供跟踪扩展

public partial class ExtendedNorthwindEntities : NorthwindEntities {
    private TextWriter logOutput;

    public ExtendedNorthwindEntities(string connectionString)
        : base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
                connectionString,
                "EFTracingProvider")) {
    }

    #region Tracing Extensions

    private EFTracingConnection TracingConnection {
        get { return this.UnwrapConnection<EFTracingConnection>(); }
    }

    public event EventHandler<CommandExecutionEventArgs> CommandExecuting {
        add { this.TracingConnection.CommandExecuting += value; }
        remove { this.TracingConnection.CommandExecuting -= value; }
    }

    public event EventHandler<CommandExecutionEventArgs> CommandFinished {
        add { this.TracingConnection.CommandFinished += value; }
        remove { this.TracingConnection.CommandFinished -= value; }
    }

    public event EventHandler<CommandExecutionEventArgs> CommandFailed {
        add { this.TracingConnection.CommandFailed += value; }
        remove { this.TracingConnection.CommandFailed -= value; }
    }

    private void AppendToLog(object sender, CommandExecutionEventArgs e) {
        if (this.logOutput != null) {
            this.logOutput.WriteLine(e.ToTraceString().TrimEnd());
            this.logOutput.WriteLine();
        }
    }

    public TextWriter Log {
        get { return this.logOutput; }
        set {
            if ((this.logOutput != null) != (value != null)) {
                if (value == null) {
                    CommandExecuting -= AppendToLog;
                }
                else {
                    CommandExecuting += AppendToLog;
                }
            }

            this.logOutput = value;
        }
    }

    #endregion
}

第 3 步:附加到日志属性

var context = new ExtendedNorthwindEntities("name=\"NorthwindEntities\"");

context.Log = System.Console.Out;

【讨论】:

  • 我没有使用 ObjectContext,但我使用的是 CodeOnly DbContext 对象,它似乎不支持任何这些。
  • 在您的示例中,您继承的“NorthwindEntities”是什么?什么样的课等等?
  • 我也没有使用任何单元测试,我不知道你在帖子的第一部分在说什么。
  • 啊哈!我得到它。 DbContext 在其 Database 属性中有一个 ObjectContext 的实例。我可以将其抽象为获取 Log 属性。谢谢!!
  • 不...这不太有效。你能告诉我什么是“NorthwindEntities”吗?我仍然对此感到迷茫。
【解决方案2】:

Express Edition 是否支持扩展事件?如果是这样,这将以与 Profiler 类似的方式捕获语句和 sp 完成的事件。

编辑:我已将其更改为使用内存目标而不是文件目标。理想情况下,取消注释 WHERE 部分并替换为适当的用户名以仅捕获感兴趣的事件,或者您可以使用 WHERE (([sqlserver].[session_id]=(56))) 按 spid 进行过滤。

IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='test_trace')
    DROP EVENT SESSION [test_trace] ON SERVER;
CREATE EVENT SESSION [test_trace]
ON SERVER
ADD EVENT sqlserver.sp_statement_completed(
     ACTION (package0.callstack, sqlserver.session_id, sqlserver.sql_text)
    -- WHERE (([sqlserver].[username]='Domain\Username'))
    ),
ADD EVENT sqlserver.sql_statement_completed(
     ACTION (package0.callstack, sqlserver.session_id, sqlserver.sql_text)
     --WHERE (([sqlserver].[username]='Domain\Username'))
     )
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY = 4096KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, 
MAX_DISPATCH_LATENCY = 1 SECONDS, MAX_EVENT_SIZE = 0KB, 
MEMORY_PARTITION_MODE = NONE, TRACK_CAUSALITY = OFF, STARTUP_STATE = OFF)

ALTER EVENT SESSION [test_trace] ON SERVER STATE = START

并查看结果(使用Adam Machanic's XE Code Generator 生成的查询)

DECLARE 
    @session_name VARCHAR(200) = 'test_trace'

SELECT 
    pivoted_data.* 
FROM 
( 
 SELECT MIN(event_name) AS event_name,
     MIN(event_timestamp) AS event_timestamp,
     unique_event_id,
     CONVERT ( BIGINT, MIN (
         CASE
             WHEN d_name = 'cpu'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [cpu],
     CONVERT ( BIGINT, MIN (
         CASE
             WHEN d_name = 'duration'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [duration],
     CONVERT ( BIGINT, MIN (
         CASE
             WHEN d_name = 'object_id'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [object_id],
     CONVERT ( INT, MIN (
         CASE
             WHEN d_name = 'object_type'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [object_type],
     CONVERT ( DECIMAL(28,0), MIN (
         CASE
             WHEN d_name = 'reads'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [reads],
     CONVERT ( VARCHAR(MAX), MIN (
         CASE
             WHEN d_name = 'session_id'
             AND d_package IS NOT NULL
             THEN d_value
         END ) ) AS [session_id],
     CONVERT ( INT, MIN (
         CASE
             WHEN d_name = 'source_database_id'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [source_database_id],
     CAST((SELECT CONVERT ( VARCHAR(MAX), MIN (
         CASE
             WHEN d_name = 'sql_text'
             AND d_package IS NOT NULL
             THEN d_value
         END ) )  AS [processing-instruction(x)] FOR XML PATH('') ) AS XML) AS [sql_text],
     CONVERT ( DECIMAL(28,0), MIN (
         CASE
             WHEN d_name = 'writes'
             AND d_package IS NULL
             THEN d_value
         END ) ) AS [writes]
 FROM
    ( 
        SELECT 
            *, 
            CONVERT(VARCHAR(400), NULL) AS attach_activity_id 
        FROM 
        ( 
            SELECT 
                event.value('(@name)[1]', 'VARCHAR(400)') as event_name, 
                event.value('(@timestamp)[1]', 'DATETIME') as event_timestamp, 
                DENSE_RANK() OVER (ORDER BY event) AS unique_event_id, 
                n.value('(@name)[1]', 'VARCHAR(400)') AS d_name, 
                n.value('(@package)[1]', 'VARCHAR(400)') AS d_package, 
                n.value('((value)[1]/text())[1]', 'VARCHAR(MAX)') AS d_value, 
                n.value('((text)[1]/text())[1]', 'VARCHAR(MAX)') AS d_text 
            FROM 
            ( 
                SELECT 
                    ( 
                        SELECT 
                            CONVERT(xml, target_data) 
                        FROM sys.dm_xe_session_targets st 
                        JOIN sys.dm_xe_sessions s ON 
                            s.address = st.event_session_address 
                        WHERE 
                            s.name = @session_name 
                            AND st.target_name = 'ring_buffer' 
                    ) AS [x] 
                FOR XML PATH(''), TYPE 
            ) AS the_xml(x) 
            CROSS APPLY x.nodes('//event') e (event) 
            CROSS APPLY event.nodes('*') AS q (n) 
        ) AS data_data 
    ) AS activity_data 
    GROUP BY 
        unique_event_id 
) AS pivoted_data; 

【讨论】:

  • 您是否安装了 Management Studio? (或 SQL Express 等价物)您应该可以在那里运行它。我在功能比较矩阵中找不到任何关于 Express 版本是否支持扩展事件的信息,所以我认为它们很可能或者应该被列出。
  • Msg 25602, Level 17, State 21, Line 14 目标“CE79811F-1A80-40E1-8F5D-7445A3F375E7.package0.asynchronous_file_target”在初始化期间遇到配置错误。无法将对象添加到事件会话中。
  • @Stacey - 这可能是文件权限的事情。我已将帖子中的代码更改为不写入文件系统目标。
  • 好吧,如果我运行这段代码,那么数据库是打开的,所以没有一个查询可以运行......
  • @Stacey - 我看到你已经解决了,但只是好奇你的意思是什么? (这是我不知道的 Express 版本的一些限制吗?)
猜你喜欢
  • 1970-01-01
  • 2013-03-11
  • 2021-09-23
  • 2016-10-27
  • 2011-01-15
  • 1970-01-01
  • 2021-09-17
  • 2015-09-14
  • 1970-01-01
相关资源
最近更新 更多