查看LINQ生成的SQL - Cast异常

时间:2014-01-08 12:29:37

标签: c# sql linq entity-framework

我想描述在与Entity Framework交谈时生成的SQL LINQ,但我遇到了异常。我在SO上发现了ToTraceString()代码,但它抛出了:

  

无法投射类型的对象   'WhereEnumerableIterator`1 [Models.DeviceLogEntry]'   输入'System.Data.Objects.ObjectQuery'。

EF定义:

public virtual ICollection<DeviceLogEntry> Errors { get; set; }

代码

var result = from e in dbDevice.Errors
             where e.Current == true && e.LogEntryType == Models.DeviceLogEntryType.Error
             select e;

var trace = ((System.Data.Objects.ObjectQuery)result).ToTraceString();

1 个答案:

答案 0 :(得分:2)

实际上,您的result类型为DbQuery<DeviceLogEntry>,而不是ObjectQueryDbQuery<T>是适用于InternalQuery的适配器,使用ObjectQuery,但两者都是内部的,不能从公共API获得)。但是如果你想跟踪生成的查询,那很简单 - 只需在查询上调用ToString()

 var trace = result.ToString();

DbQuery<T>已覆盖ToString()方法,该方法在内部调用objectQuery.ToTraceString()并返回基础查询的字符串表示形式。

UPDATE :因此事实证明dbDeviceDevice实体的实例,而Errors只是一个导航属性,然后实体框架可以在以下方式 - 如果启用了延迟加载,则在首次访问Errors属性期间,它会将所有实现的DeviceLogEntry实体加载到dbDevice实体。这是由内部发生的,由EF为延迟加载生成的代理类。你无法获得在这种情况下执行的SQL。对Errors集合的所有查询都将在内存中进行(即,它将是Linq to Objects而不是Linq to Entities)。因此,您的result将是已加载日志的简单内存迭代器。

要查看生成的查询,您应该在DbSet类上为DeviceLogEntries创建DbContext。然后你应该定义查询:

var query =  from e in db.DeviceLogEntries
             where e.Current == true && 
                   e.LogEntryType == Models.DeviceLogEntryType.Error &&
                   e.DeviceId = dbDevice.Id // or use join
             select e;

现在query.ToString()将向您显示由Entity Framework生成的SQL查询。

注意:如果您使用的是Entity Framework 6,那么您还可以使用db.Database.Log来记录已执行的数据库查询。