我想描述在与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();
答案 0 :(得分:2)
实际上,您的result
类型为DbQuery<DeviceLogEntry>
,而不是ObjectQuery
(DbQuery<T>
是适用于InternalQuery
的适配器,使用ObjectQuery
,但两者都是内部的,不能从公共API获得)。但是如果你想跟踪生成的查询,那很简单 - 只需在查询上调用ToString()
:
var trace = result.ToString();
DbQuery<T>
已覆盖ToString()
方法,该方法在内部调用objectQuery.ToTraceString()
并返回基础查询的字符串表示形式。
UPDATE :因此事实证明dbDevice
是Device
实体的实例,而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
来记录已执行的数据库查询。