奇怪的LINQ异常(索引超出范围)

时间:2008-10-10 14:49:21

标签: c# linq linq-to-sql

我有一张桌子,我们会打电话给Users。此表具有在SQL Server中定义的单个主键 - 自动增量int ID

有时,针对此表的LINQ查询失败并出现"Index was outside the range"错误 - 即使是最简单的查询。查询本身不使用任何索引器。

例如:

User = Users.Take(1);

IEnumerable<Users> = Users.ToList();

两个查询都抛出了同样的错误。使用调试器Visualizer查看生成的查询 - 我在SQL中复制并粘贴查询,它工作正常。我也点击了可视化工具上的“执行”,它工作正常。但是,执行代码本身会引发此错误。我没有在类上实现任何部分方法,所以没有任何事情发生在那里。如果我重新启动我的调试器,问题就会消失,只是在几个小时之后再次随机地重新启动它。更重要的是,我在生产中运行的应用程序的错误日志中看到了这个错误。

我在我的应用程序中对我的数据库中的十几个不同实体进行了大量的LINQ,但我只在与表中的特定实体相关的查询中看到此问题。一些谷歌搜索表明这个问题可能与我的模型和另一个实体之间指定的错误关系有关,但我没有与此对象的任何关系。它似乎在95%的时间里工作,只是其他5%的失败。

我已从设计器中完全删除了该对象,并从“刷新的”服务器浏览器重新添加该对象,但这并没有解决问题。

有什么想法在这里发生了什么?

这是完整的错误消息和堆栈跟踪:

  

指数超出范围。必须是非负数且小于   集合。参数名称:索引位于   System.Data.Linq.SqlClient.SqlProvider.Execute(表达式查询,   QueryInfo queryInfo,IObjectReaderFactory factory,Object []   parentArgs,Object [] userArgs,ICompiledSubQuery [] subQueries,Object   lastResult)at   System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(表达式查询,   QueryInfo [] queryInfos,IObjectReaderFactory factory,Object []   userArguments,ICompiledSubQuery [] subQueries)at   System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(表达式   查询)   System.Data.Linq.Table 1.System.Linq.IQueryProvider.Execute[TResult](Expression expression) at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable 1个来源,   表达式`1谓词)在MyProject.FindUserByType(String typeId)

编辑:根据要求,下面是表格架构的副本。

CREATE TABLE [dbo].[Container](
[ID] [int] IDENTITY(1,1) NOT NULL,
[MarketCode] [varchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Description] [varchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Capacity] [int] NOT NULL,
[Volume] [float] NOT NULL
 CONSTRAINT [PK_Container] PRIMARY KEY CLUSTERED 
(
[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

编辑:堆栈跟踪显示FirstOrDefault,但我使用Take()ToList()重复了错误。堆栈跟踪在所有这些之间是相同的,只是interchangnig FirstOrDefault/Take/ToList。从堆栈向下移动到SqlProvider.Execute实际上是相同的。

6 个答案:

答案 0 :(得分:5)

这几乎肯定不是每个人的根本原​​因,但我在我的项目中遇到了这个完全相同的异常 - 并且发现根本原因是在构造实体类期间抛出了异常。奇怪的是,真正的异常是“丢失”,而是表现为一个ArgumentOutOfRange异常,它起源于检索对象的Linq语句的迭代器。

如果您收到此错误并且已在POCO上引入了OnCreated或OnLoaded方法,请尝试逐步执行这些方法。

答案 1 :(得分:1)

我会说你有一个模特 - &gt;数据库在某处不匹配。当我在这样的情况下像你一样绝望时,我通常会启动VS.NET,创建一个新的控制台应用程序,并重建DBML的一部分,该部分引用此查询中感兴趣的实体,然后重新运行。您可能会发现在这种隔离中,查询有效。您是否通过填写部分方法来定制任何实体定义,尤其是那些在创建时触发的方法?

答案 2 :(得分:0)

系统库中发生异常,您的故事让我觉得问题不在您的代码中。架构最近有变化吗?你的地图是否正确?

答案 3 :(得分:0)

由于该表的linq对象和数据库字段不相同而发生此问题。

答案 4 :(得分:0)

我也有这个问题并解决了它。

现在我理解错误是对Linq数据上下文的错误使用,但也许我的经验仍然可以帮助其他人理解为什么他们会收到此错误。

Linq数据上下文不适合同时运行。因此,创建运行异步的多个任务并不理想。请检查以下示例代码以了解该问题:

using(var ctx = new LinqDataContext())
{
    List<Task> tasks = new List<Task>();
    for(int i=0;i<1000;i++)
    {
        var task = Task.Run(() => {
            var customer = ctx.Customers.SingleOrDefault(o => o.Id == i);
            customer.DoSomething();
        }
        tasks.Add(task);
    }
    Task.WaitAll(tasks);
}

在我的场景中,我将数据上下文作为参数传递给较长的调用堆栈,并在此过程中调用异步方法。所以它不像上面的例子那么明显。但也许这可以帮助别人: - )

答案 5 :(得分:-1)

在黑暗中拍摄:

您正在使用循环变量作为参数调用循环体内的MyProject.FindUserByType(String typeId)。

不要直接使用循环变量。

foreach(string s in myTypeList)
{
  //GetUserByType(s);  //Ooo, bad
  string tempstring = s;
  GetUserByType(tempstring); 
}

如果情况确实如此,我将更新此答案以解释为什么直接使用循环变量是一种不好的做法(更新问题后显示循环)。