代码之家  ›  专栏  ›  技术社区  ›  Mark S. Rasmussen

可查询.single上的indexOutOfRangeException

  •  7
  • Mark S. Rasmussen  · 技术社区  · 17 年前

    我有一个ASP.NET网站,它已经运行了很长一段时间,最近没有任何变化。从一个小时到下一个小时,我开始在一行中接收indexoutofrangeexception,在该行中我执行这样的LINQ查询:

    var form = SqlDB.GetTable<ORMB.Form, CDB>()
        .Where(f => f.FormID == formID)
        .Single();
    

    form是一个poco对象,具有linq-to-sql属性,将其映射到一个mssql表(映射被验证为正确的)。stacktrace如下:

    System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
       at System.Collections.Generic.List`1.Add(T item)
       at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user)
       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.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression)
       at System.Linq.Queryable.Single[TSource](IQueryable`1 source)
       at GetForm.Page_Load(Object sender, EventArgs e)
    

    反射System.Collections.Generic.List.Add显示以下代码:

    public void Add(T item)
    {
        if (this._size == this._items.Length)
        {
            this.EnsureCapacity(this._size + 1);
        }
        this._items[this._size++] = item;
        this._version++;
    }
    

    唯一应该倾向于indexofoutrangeexception的行是这个。_items[this._size++]=item,但是我看不到我是如何影响这个的。

    我可以通过执行AppDomain循环来解决这个问题,因此它一定与缓存相关。如果这很重要,则在DataContext上关闭对象跟踪。

    我的直觉是这可能是一个线程问题,SQLConnectionManager在名为“用户”的列表字段中缓存了IConnectionUsers。如果两个线程同时进入添加方法,是什么阻止了以下情况的发生:

    T1: Add(x)
    T2: Add(y)
    T1: Since _size == _items.Length: EnsureCapacity(_size + 1)
    T2: Since _size > _items.Length: _items[_size++] = item;
    T1: _items[size++] = item <- OutOfRangeException since T2 didn't increase the capacity as needed
    

    有人吗?

    2 回复  |  直到 16 年前
        1
  •  3
  •   csgero    17 年前

    您共享一个通用的数据上下文吗?这将解释您所描述的线程问题,因为DataContext不是线程安全的。

        2
  •  0
  •   Neil Barnwell    17 年前

    检查DBML中的所有“主键”列是否都与数据库表中的主键相关。我刚遇到这样一种情况,设计师决定在DBML中添加一个额外的pk列,这意味着在保存时Linq to SQL找不到外键的两边。