一个具有相同键的项已经被添加。

9

我在生产服务器上随机遇到了这个错误,以下是错误的堆栈跟踪。 我正在使用linq to sql和.net 4.0。

System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Data.Linq.DataContext.GetTable(MetaTable metaTable)
   at System.Data.Linq.DataContext.GetTable[TEntity]()
   at UserManagement.Models.EvoletDataContext.get_sysModules() in D:\MyProj\Models\datamdl.designer.cs:line 1294
   at UserManagement.Models.FilterRepository.GetModuleHead(String actionName) in D:\MyProj\Models\FilterRepository.cs:line 14
   at UserManagement.Models.DummyAttrib.OnAuthorization(AuthorizationContext filterContext) in D:\MyProj\Models\Filters.cs:line 44
   at Glimpse.Net.Plumbing.GlimpseAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
   at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
   at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
   at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

第14行的代码如下所示,我也包括了数据上下文

private EvoletDataContext db = new EvoletDataContext();

        public sysModule GetModuleHead(string actionName)
        {
            var val =  (from mod in db.sysModules
                        where
                        mod.ModuleActionResult.ToLower().Equals(actionName.ToLowerInvariant())
                    select mod).SingleOrDefault();
            return val;
    }

第44行的代码是

public class DummyAttrib:FilterAttribute,IAuthorizationFilter
    {

        private readonly FilterRepository _filterRepository = new FilterRepository();
        public void OnAuthorization(AuthorizationContext filterContext) 
        {
            if (!filterContext.Controller.ControllerContext.IsChildAction && !filterContext.HttpContext.Request.IsAjaxRequest())
            {
                var cont = (ApplicationController)filterContext.Controller;
                                var modhead = _filterRepository.GetModuleHead(filterContext.RouteData.Values["action"].ToString());
                if (cont.DocumentID != 0 && modhead !=null) 
                {
                    if (_filterRepository.hasRightonModuleChildren(modhead.ModuleID, cont.RoleID))
                        return;
                }
                if (cont.DocumentID == 0 && !filterContext.RouteData.Values["action"].ToString().ToLowerInvariant().Equals("index"))
                {
                    filterContext.Result = new RedirectResult("/account.mvc/AccessDenied");
                    return;
                }

                if (!_filterRepository.hasRighton(cont.DocumentID, cont.RoleID))
                {
                    filterContext.Result = new RedirectResult("/account.mvc/AccessDenied");
                    return;
                }

            }
        }
    }

请分享异常堆栈跟踪中提到的行的代码。 - Rami Alshareef
问题已更新。请查看第14行的代码,其他位置的代码类似。 - Tassadaque
6个回答

11
LINQ保持了一个“缓存”已经使用过的表的列表,以避免多次查找它们。
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Data.Linq.DataContext.GetTable(MetaTable metaTable)
at System.Data.Linq.DataContext.GetTable[TEntity]()
你试图使用的表在数据上下文中之前没有被使用过,因此它正在被添加到“缓存”中。这可能失败的其中一种方式是如果你同时从多个线程调用GetTable(),这表明你正在为整个应用程序使用单个数据上下文,这不是一个好主意。此外,如果你要并行执行任务,请勿使用相同的数据上下文。

1
我将我的应用程序移植到EF,但您能否提供一些关于如何使用datacontext的最佳实践参考? - Tassadaque
@Tassadaque 我对 EF 的经验不够丰富,但我认为相同的指导方针适用:
  • 不要让多个线程同时访问数据上下文。
  • 对于每个工作项(无论是来自请求、UI 命令等),使用一个新的数据上下文。
- ErikHeemskerk
如果我在每个 repository 中实例化 datacontext,mycontainer context = new mycontainer(); 那么超过一个线程将无法访问 datacontext,我是对的吗?我通过 repositories 访问数据库的所有权限。 - Tassadaque
1
除非有多个线程访问同一个存储库实例。如果我在之前的评论中没有表达清楚,允许多个线程访问相同的数据上下文_class_,但不允许访问相同的_instance_。如果两个线程访问同一个存储库实例,则它们也将访问相同的数据上下文实例。 - ErikHeemskerk

2

我有一个同样的问题。我已经解决了它。 实际上,我的ViewModel中有一个重复的属性名称。 一个属性在BaseViewModel中,另一个属性在派生模型中。

例如:

public class BaseviewModel{
  public int UserId { get; set; }
}


 public class Model : BaseViewModel
 {
     public int UserId { get; set; }
 }

我已经将它们更改为:
  public class BaseviewModel{
     public int UserId { get; set; }
  }


  public class Model : BaseViewModel
  {
      public int User_Id { get; set; }
  }

现在它的运行良好。

1

0

我们在生产服务器上部署了几个月后遇到了类似的问题。经过一些研究,我发现有时候 LINQ 会自动关闭连接,这可能是问题所在。现在我们通过静态扩展方法专门关闭所有的 LINQ TO SQL 连接。示例代码:

public static void extClose(this System.Data.Linq.DataContext dataContext, bool submitChanges)
{
    if (null != dataContext && System.Data.ConnectionState.Closed != dataContext.Connection.State)
    {
        if (true == submitChanges)
        {
            dataContext.SubmitChanges();
        }
        dataContext.Connection.Close();
    }
}

0

我在一个现有的应用程序中遇到了与EF 4.1相同的问题。

发生了什么?EF 4.1需要.NET Framework 4.0。Windows更新将.NET Framework 4.0替换为4.5,我得到了与您相同的错误。

解决方案是卸载.NET 4.5并安装.NET 4.0。

在生产机器上,您应该设置Windows跳过更新到4.5。


0

我曾经遇到过同样的错误,但原因是我的多对一关系中定义了错误的端点作为关系中的主键和次要键。

使用SQL Server Management Studio设计器时,从子表拖放到父表太容易了,可能会忽略创建关系时的差异。

请检查所有关系是否正确定义。


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