我一直在使用Linq-to-SQL很长一段时间,而且效果很好。但是,最近我一直在尝试使用它来提取大量数据并且遇到了一些问题。 (当然,我理解L2S可能不是这种特殊处理的正确工具,但这就是为什么我在试验 - 找到它的极限。)
以下是代码示例:
var buf = new StringBuilder();
var dc = new DataContext(AppSettings.ConnectionString);
var records = from a in dc.GetTable<MyReallyBigTable>() where a.State == "OH" select a;
var i = 0;
foreach (var record in records) {
buf.AppendLine(record.ID.ToString());
i += 1;
if (i > 3) {
break; // Takes forever...
}
}
一旦我开始迭代数据,查询就会按预期执行。当单步执行代码时,我立即进入循环,这正是我所希望的 - 这意味着L2S似乎在幕后使用DataReader而不是首先拉取所有数据。但是,一旦我到达break
,查询将继续运行并拉出所有其余记录。以下是我对SO社区的问题:
1。)有没有办法阻止Linq-to-SQL以DataReader
的方式在中间执行一个非常大的查询?
2.如果执行大型Linq-to-SQL查询,是否有办法阻止DataContext填充返回的每个对象的更改跟踪信息。基本上,我可以使用DataReader
技术以短暂的对象生命周期进行大型查询,而不是填充内存吗?
如果这不是DataContext
本身内置的功能,并且需要通过一些自定义扩展功能,我没关系。我只是想利用Linq的简单性和强大功能来处理夜间处理任务的大型查询,而不是依靠T-SQL来处理所有事情。
答案 0 :(得分:7)
1。)是否有办法阻止Linq-to-SQL完成真正的执行 中间的大问题你的方式 可以使用DataReader吗?
不完全。最终执行查询后,基础SQL语句将返回匹配记录的结果集。查询将推迟到该点,但不会在遍历期间延迟。
对于您的示例,您可以简单地使用records.Take(3)
但我了解您暂停该过程的实际逻辑可能是SQL外部的或不易翻译。
您可以通过构建强类型LINQ查询然后使用旧式ADO.NET执行它来使用组合方法。缺点是你失去了到类的映射,并且必须手动处理SqlDataReader结果。这方面的一个例子如下所示:
var query = from c in Customers
where c.ID < 15
select c;
using (var command = dc.GetCommand(query))
{
command.Connection.Open();
using (var reader = command.ExecuteReader())
{
int i = 0;
while (reader.Read())
{
Customer c = new Customer();
c.ID = reader.GetInt32(reader.GetOrdinal("ID"));
c.Name = reader.GetString(reader.GetOrdinal("Name"));
Console.WriteLine("{0}: {1}", c.ID, c.Name);
i++;
if (i > 3)
break;
}
}
}
2.。)如果你执行一个大的Linq-to-SQL查询,有没有办法阻止 DataContext来自填充 更改每个人的跟踪信息 对象返回。
如果您对特定查询的意图是将其用于只读目的,则可以通过将DataContext.ObjectTrackingEnabled property设置为false来禁用对象跟踪以提高性能:
using (var dc = new MyDataContext())
{
dc.ObjectTrackingEnabled = false;
// do stuff
}
您还可以阅读此MSDN主题:How to: Retrieve Information As Read-Only (LINQ to SQL)。