LINQ to SQL数据上下文日志不显示WHERE子句

时间:2012-11-15 23:16:51

标签: sql-server linq linq-to-sql linq-to-objects

以下是C#代码,并在两种情况下在LINQ to SQL查询中生成SQL。

<案例1
using (JulianDataContext dc = new JulianDataContext(this.CurrentConnectionString))
{
#if DEBUG
    dc.Log = new DebugTextWriter();
#endif

    IEnumerable<UserNewsfeedDeliveryTime> temp = dc.UserNewsfeedDeliveryTimes.Where(u => u.NewsfeedEmailPeriodicity > 0 && DateTime.Today >= u.NextNewsfeedDelivery.Value.Date);

    ids = temp.Select(p => p.Id).ToList();
}

SELECT [t0].[Id], [t0].[NewsfeedEmailPeriodicity], [t0].[LastSentNewsfeedEmail], [t0].[NextNewsfeedDelivery]
FROM [dbo].[UserNewsfeedDeliveryTimes] AS [t0]
WHERE ([t0].[NewsfeedEmailPeriodicity] > @p0) AND (@p1 >= CONVERT(DATE, [t0].[NextNewsfeedDelivery]))
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @p1: Input DateTime (Size = -1; Prec = 0; Scale = 0) [15-11-2012 00:00:00]
<案例2
using (JulianDataContext dc = new JulianDataContext(this.CurrentConnectionString))
{
#if DEBUG
            dc.Log = new DebugTextWriter();
#endif
    IEnumerable<UserNewsfeedDeliveryTime> temp = dc.GetTable<UserNewsfeedDeliveryTime>();

    temp = temp.Where(u => u.NewsfeedEmailPeriodicity > 0 && DateTime.Today >= u.NextNewsfeedDelivery.Value.Date);

    ids = temp.Select(p => p.Id).ToList();
}
SELECT [t0].[Id], [t0].[NewsfeedEmailPeriodicity], [t0].[LastSentNewsfeedEmail], [t0].[NextNewsfeedDelivery]
FROM [dbo].[UserNewsfeedDeliveryTimes] AS [t0]

差异

这两个linq查询之间的区别:

dc.UserNewsfeedDeliveryTimes

dc.GetTable&LT; UserNewsfeedDeliveryTime&GT;()

为什么呢?可能是这样,在案例2中,LINQ to SQL是从数据库中检索所有数据并通过过滤内存中的所有对象来完成查询吗?

如果是这样,我们如何才能保持这种通用性并仍然强制生成所有T-SQL?

解决方案

这两个答案都是正确的,但我必须选一个,对不起!我认为在这种情况下添加它是有趣的,因为我改为使用IQueryable(继承自IEnumerable),在这一行:

temp = temp.Where(u =&gt; u.NewsfeedEmailPeriodicity&gt; 0&amp;&amp; DateTime.Today&gt; = u.NextNewsfeedDelivery.Value.Date);

我有两个重载方法,一个来自IQueryable接口,另一个来自IEnumerable接口。

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

所以我必须将我的谓词明确地转换为Expression&gt;谓词,否则IEnumerable接口方法将在编译时被选中,如果我没有弄错,我会得到一些动态的sql异常,说无法生成T-SQL。

2 个答案:

答案 0 :(得分:2)

尝试使用 IQueryable 而不是 IEnumerable

很奇怪,因为在我的例子中我得到了相反的结果,即IEnumerable,案例1工作得很快,案例2检索所有数据。但是使用IQueryable解决了这个问题。

答案 1 :(得分:2)

据我了解,IEnumerable不会转换IQueryable所持有的原始查询信息。这几乎就像演员阵容在施法点冻结了对IQueryable查询的任何更改。如果您查看MSDN,则IQueryable会继承IEnumerable

http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx

因此,您会看到此行为。 LINQ-SQL与IQueryable一起使用非常重要,除非您希望查询冻结,并将其转换为IEnumerable

在第一个示例中,where包含原始查询。 select因此不会生成查询。

在第二个示例中,您将表格本身捕获到IEnumerable。除此之外的任何更改都在原始查询之上的内存中完成。

如果您认为IEnumerable where版本的IQueryable将无法转换{{1}}的原始数据,因为广告投放以及继承的工作方式。

当您还考虑延迟加载以及LINQ如何工作时,这似乎是有道理的。 对我来说这是一个很大的烦恼,因为它可能会导致你产生一些糟糕的表演代码。