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

10

我有一张表格,我们称其为Users。在SQL Server中,这个表格只定义了一个自增的主键int ID

有时,我的针对这个表格的LINQ查询会因为一个"Index was outside the range"错误而失败——即使是最简单的查询。查询本身没有使用任何索引器。

例如:

User = Users.Take(1);
或者
IEnumerable<Users> = Users.ToList();
这两个查询都产生了相同的错误。使用调试器 Visualizer 查看生成的查询 - 我复制并粘贴 SQL 查询,它可以正常工作。我还在可视化程序中点击“执行”,也能正常工作。但是,单独执行代码会抛出此错误。我没有在类上实现任何部分方法,因此那里什么都没有发生。如果我重新启动调试器,问题就消失了,只有在几个小时后不定时地重新出现。更为关键的是,我在运行中的应用程序的错误日志中看到了这个 bug。
我的应用程序中做了大量的 LINQ,针对数据库中约十几个不同的实体,但我只在与表中特定实体相关的查询中遇到了这个问题。一些搜索表明,这个问题可能与模型及另一个对象之间指定的不正确关系有关,但我没有任何关联这个对象。它似乎在 95% 的时间内工作正常,只有在其他 5% 的情况下失败。
我已经从设计器中完全删除了该对象,并从“刷新”的服务器浏览器中重新添加了它,但问题并没有得到解决。
这里是完整的错误消息和堆栈跟踪:
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression) at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) at 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()复制了错误。在所有这些情况下,堆栈跟踪是相同的,只需交换FirstOrDefault / Take / ToList 即可。向下移动到SqlProvider.Execute的操作实际上是相同的。


不知道正在发生什么,但很迷人!如果所有其他方法都失败了,您可以尝试使用General Linq项目列表:http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=123&SiteID=1。 - Marc Gravell
如果我们能看到表的定义,可能会有所帮助。 - KyleLanser
堆栈跟踪显示FirstOrDefault,但代码示例没有显示此方法。请展示使用FirstOrDefault的代码或确认它未被调用。 - Amy B
可能是与此问题相同:https://dev59.com/0EXRa4cB1Zd3GeqPsYW4 - Amy B
这个错误在许多客户端机器上发生,只在使用Windows XP的机器上出现。我找到了一个热补丁来解决这个问题。i386: http://hotfixv4.microsoft.com/.NET%20Framework%203.5%20-%20Windows%20Server%202003,%20WindowsXP,%20Windows%20Vista,%20Windows%20Server%202008%20(MSI)/sp1/DevDiv975687/30729.5821/free/448814_intl_i386_zip.exe x64: http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=963657&kbln=en-us - gpiccin
显示剩余3条评论
5个回答

5

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

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


实际上,这是另一种被“超出范围”异常隐藏的异常。在我的情况下,我遇到了同样的问题,原因是我想要修改的对象处于无效的上下文中。 - Hannish

1
我认为你在模型和数据库之间存在不匹配的情况。当我像你这样绝望的时候,通常会启动VS.NET,创建一个新的控制台应用程序,并重新构建引用此查询中感兴趣的实体的DBML部分,然后重新运行。你可能会发现,在这种隔离的情况下,查询可以正常工作。你是否自定义了任何实体定义,填写了部分方法,特别是在创建时触发的方法?

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);
}

在我的情况下,我将数据上下文作为参数传递给了一个较长的调用堆栈,并在途中调用了异步方法。因此,这并不像上面的例子那样显而易见。但是也许这可以帮助其他人 :-)

0

异常发生在一个系统库中,你的描述让我觉得问题不在你的代码里。最近模式有没有改变?你的映射是否正确?


模式最近没有改变,尽管我有相当长的时间出现问题。我已经通过服务器浏览器删除了罪犯表并重新添加了它,但没有效果。 - Matt

0

这个问题是由于linq对象和该表的数据库字段不相同导致的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接