LinqToSql 查询将不需要的数据加载到内存中

本文关键字:加载 内存 数据 查询 不需要 LinqToSql | 更新日期: 2023-09-27 17:55:55

我正在通过linq to sql模拟链接服务器上的联接。我的问题是,linqtosql 似乎将 y.Xstatus 的所有行都放入内存中,然后进行连接。如果这是真的,我如何将所有内存保留在sql服务器上(并且仍然执行跨数据上下文连接操作),如果这不是真的,发生了什么正在吞噬我所有的RAM?

var x = new fooDataContext();
var y = new barDataContext();
var allXNotDeleted = (from w in x.CoolTable
                      where x.IsDeleted != false).ToList();//for our demo this returns 218 records
var allXWithCompleteStatus = (from notDeleted in allXNotDeleted
                              join s in y.XStatuses on notDeleted.StatusID equals s.StatusID
                              where s.StatusID == 1
                              select notDeleted).Tolist();// insert massive memory gobbler here
return allXwithCompleteStatus;

编辑:试图实现凯文巴布科克的想法

    using (x = new fooDataContext())
    using (var y = new barDataContext())
    {
        var n = (from notDeleted in x.GetTable<CoolTable>()
             join z in y.GetTable<Xstatus>() on x.StatusID equals z.StatusID
             where z.StatusID == 1 and x.IsDeleted != false
             select x).ToList();
    }

这仍然会引发跨上下文查询例外

LinqToSql 查询将不需要的数据加载到内存中

不能

直接对数据库执行跨数据上下文查询。在内存中获取其中一个记录集 (ToList()) 会强制另一个连接在内存中进行处理。

如果要在sql服务器上执行所有操作,则必须将每个实体都放在同一个DataContext中。

我建议不要在allXNotDeleted上调用ToList作为开始。这会将这些记录拉入内存,这可能意味着在执行第二次查询时无法避免将所有其他数据拉入内存。

编辑:

另外,如果您的表特别大,并且您只需要几列中的数据,则可以在数据库对象模型中为不需要的列设置Delay Loaded True

编辑2:

我刚刚注意到这两个查询来自不同的上下文。在这种情况下,我建议您创建一个存储过程并从其中一个上下文中调用它。sproc 应该负责跨越上下文。

不要在allXNotDeleted上调用ToList()。这将具体化内存中的这些记录,这将导致整个XStatuses表也在内存中具体化以执行联接。

试试这个:

using(var context = new DataContext(connectionString))
{
    var allXNotDeleted =
        from w in context.GetTable<CoolTable>()
        where x.IsDeleted != false;
    var allXWithCompleteStatus = (
        from notDeleted in allXNotDeleted
        join s in context.GetTable<XStatuses>()
            on notDeleted.StatusID equals s.StatusID
        where s.StatusID == 1
        select notDeleted)
        .ToList();
    return allXwithCompleteStatus;
}

这只会将单个查询发送到 SQL Server,并且只会具体化从查询返回的"notDeleted"值。不要忘记将DataContext实例包装在 using 语句中,以便在它们脱离上下文时正确调用Dispose()

另外,你的意思是用IsDeleted != false过滤CoolTable吗?这相当于 IsDeleted == true ,对我来说,这表明您要连接所有已删除的记录(变量的名称 allXNotDeleted 似乎与之矛盾)。

编辑:更新了代码以使用单个DataContext实例,这应该消除"查询包含对另一个 DataContext 的引用"错误。如果不使用派生的 DataContext 类,则需要将ConnectionString传递给 DataContext 构造函数。