我有一个表,我们将调用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工厂,Object[]parentArgs,Object[]userArgs,ICompiledSubQuery[]subQueries,ObjectlastResult)System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(表达式查询,QueryInfo[]queryInfos,IObjectReaderFactory工厂,Object[]userArguments,ICompiledSubQuery[]subQueries)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谓词)。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]
EDIT:堆栈跟踪显示FirstOrDefault
,但我使用Take()
和ToList()
重复了错误。堆栈跟踪在所有这些之间是相同的,只是简单地交换FirstOrDefault/Take/ToList
。从堆栈向下移动到SqlProvider.Execute
实际上是相同的。
这几乎肯定不是每个人的根本原因,但我在项目中遇到了完全相同的异常,发现根本原因是在构建实体类的过程中抛出了异常。奇怪的是,真正的异常是"丢失"的,而是表现为ArgumentOutOfRange异常,该异常源自检索对象的Linq语句的迭代器。
如果您收到此错误,并且在POCO上引入了OnCreated或OnLoaded方法,请尝试逐步执行这些方法。
我想说您在某个地方发现了模型->数据库不匹配。当我在这种情况下像你一样绝望时,我通常会启动VS.NET,创建一个新的控制台应用程序,重建DBML中引用该查询中感兴趣实体的部分,然后重新运行。您可能会发现,在这种隔离中,查询是有效的。您是否通过填写分部方法自定义了实体定义,尤其是在创建时激发的方法?
异常发生在系统库中,您的故事让我认为问题不在您的代码中。架构最近更改了吗?你的映射正确吗?
此问题是由于该表的linq对象和数据库字段不相同而发生的。
我也遇到了这个问题并解决了它。
现在我知道这个错误是对Linq数据上下文的错误使用,但也许我的经验仍然可以帮助其他人理解他们为什么会出现这个错误。
Linq数据上下文不适用于同时运行。因此,创建多个运行async的任务并不理想。检查以下样本代码以了解问题:
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);
}
在我的场景中,我将数据上下文作为一个较长调用堆栈中的参数进行传递,并在此过程中调用异步方法。所以它并不像上面的例子那么明显。但也许这可以帮助其他人:-)