【问题标题】:The SqlParameter is already contained by another SqlParameterCollectionSqlParameter 已被另一个 SqlParameterCollection 包含
【发布时间】:2013-03-09 08:34:15
【问题描述】:

我正在使用 EF DbContext SqlQuery 获取使用 PagedList (https://github.com/TroyGoode/PagedList) 的分页对象列表,我收到以下错误:

"SqlParameter 已被另一个 SqlParameterCollection 包含"

这是我的存储库代码:

var db = (DbContext)DataContext;
        const string sqlString =
            @"            
            WITH UserFollowerList
            AS 
            ( 
            SELECT uf.FollowId
            FROM UserFollow uf 
            WHERE uf.UserId = @UserId
            )
            SELECT * FROM UserFollowerList uf
            INNER JOIN [User] u ON uf.FollowId = u.UserId
            WHERE IsDeleted = 0
            "
            ;

        var userIdParam = new SqlParameter("UserId", SqlDbType.Int) {Value = userId};

        var userList =
            db.Database.SqlQuery<User>(sqlString, userIdParam)
            .ToPagedList(pageIndex, pageSize);

        return userList;

但是当我在 SqlQuery 语句上调用 ToList 扩展时,它工作正常:

var userList = db.Database.SqlQuery<User>(sqlString, userIdParam).ToList();

分页列表代码:

private PagedList(IQueryable<T> source, int pageIndex, int pageSize)
    {
        TotalItemCount = source.Count();

        PageSize = pageSize;
        PageIndex = pageIndex;
        PageCount = TotalItemCount > 0 ? (int)Math.Ceiling(TotalItemCount / (double)PageSize) : 0;

        HasPreviousPage = (PageIndex > 0);
        HasNextPage = (PageIndex < (PageCount - 1));
        IsFirstPage = (PageIndex <= 0);
        IsLastPage = (PageIndex >= (PageCount - 1));

        ItemStart = PageIndex * PageSize + 1;
        ItemEnd = Math.Min(PageIndex * PageSize + PageSize, TotalItemCount);

        // add items to internal list
        if (TotalItemCount > 0)
            Data = pageIndex == 0 ? source.Take(pageSize).ToList() : source.Skip((pageIndex) * pageSize).Take(pageSize).ToList();
    }

我已经解决了以下问题,但没有成功:

var param = new DbParameter[] { new SqlParameter { ParameterName = "UserId", Value = userId }

如何解决我遇到的错误?

【问题讨论】:

  • 你见过thisthis吗?
  • 是的,我有,但都不能解决我的问题。

标签: entity-framework-4 dbcontext sqlparameter pagedlist


【解决方案1】:

仅供参考,当我使用 EF 5 DbContext 调用带有 SqlParameters 数组的 context.ExecuteQuery&lt;my_type&gt;(...); 时,我刚刚看到了完全相同的错误消息,其中 my_type 有一个 string 但 SQL 语句为其中一个返回了一个 int参数。

错误确实是在返回映射中,但它说是 SqlParameter 应该受到指责,这让我有点想不通。

【讨论】:

  • 我在生成数据库的第一个数据层时遇到了同样的错误。错误显示“SqlParameter 已被另一个 SqlParameterCollection 包含。”但实际上,如果我直接在 Sql Managament Studio 中执行该过程,则会出现日期时间参数转换错误。
【解决方案2】:

当使用对 SqlQuery 的通用调用(例如 db.Database.SqlQuery)时,您必须迭代到返回的 Set 的最后一条记录,以便释放结果集和相关参数。 PagedList 使用 source.Take(pageSize).ToList() 不会读到源集的末尾。您可以通过在返回结果之前执行类似 foreach(User x in userList) 之类的操作来解决此问题。

【讨论】:

    【解决方案3】:

    我在http://blogs.msdn.com/b/diego/archive/2012/01/10/how-to-execute-stored-procedures-sqlquery-in-the-dbcontext-api.aspx 尝试了 Diego Vega 的以下解决方案,它对我有用:

     var person = context.Database.SqlQuery<Person>(
     "SELECT * FROM dbo.People WHERE Id = {0}", id);
    

    【讨论】:

    • 如果有人有更好的解决方案,我还是想试试。
    【解决方案4】:

    当您在(SqlQuery 或 ExecuteSqlCommand)上使用参数时,在旧查询处理之前,您不能通过另一个查询使用主题。 在 PagedList 方法中,您使用“source.Count();”首先,您再次使用“源”的最后一行。这是不正确的。 你有2个解决方案。 1-使用 SqlQuery 或 ExecuteSqlCommand 将参数发送到 PagedList 方法和新主题 2-删除 PagedList 并将您的分页参数发送到 SqlQuery 或 ExecuteSqlCommand ,如下所示:

       const string sqlString =
            @"            
            WITH UserFollowerList
            AS 
            ( 
            SELECT uf.FollowId,ROW_NUMBER() OVER(ORDER BY uf.FollowId ) RowID
            FROM UserFollow uf 
            WHERE uf.UserId = @UserId
            )
            SELECT * FROM UserFollowerList uf
            INNER JOIN [User] u ON uf.FollowId = u.UserId
            WHERE IsDeleted = 0 and RowID BETWEEN (((@PageNumber- 1) *@PageSize)+ 1) AND (@PageNumber * @PageSize))
            "
            ;
    

    【讨论】:

      【解决方案5】:

      即使这是我第一次使用单个参数查询数据库,也遇到了这个异常。并在“使用”中拥有上下文。 当我将查询参数“硬编码”到字符串中时,由于某种原因它工作正常。但是,一旦我使用 SqlParameter,它就给了我“SqlParameter 已被另一个 SqlParameterCollection 包含”

      这不起作用:

      context.Database.SqlQuery&lt;int?&gt;(query, new SqlParameter("@TableName", tableName));

      这样做了:

      context.Database.SqlQuery&lt;int&gt;(query, new SqlParameter("@TableName", tableName));

      区别在于返回类型 int?int。所以对于任何阅读本文的人。即使您确定它应该工作,也请检查您的 SqlQuery 的返回类型。

      【讨论】:

        【解决方案6】:

        这是旧的,但我遇到了同样的问题,有人在这里想到了解决方案 https://dotnetfiddle.net/GpEd95

        基本上,您需要将其拆分为几个步骤才能获得分页查询

        //step 1 set the page numbers    
        
            int pageNumber = 1;
            int pageSize = 2;
        
        //step 2 set your parameters up
        
                var parm2 = new SqlParameter("param1", "Kevin");
                var parm1  = new SqlParameter("param1", "Kevin");
                var pageParm = new SqlParameter("@p2", (pageNumber - 1) * pageSize);
                var pageSizeParm = new SqlParameter("@p3", pageSize);
        
         //step 3 split your queries up into search and count
        
                 var sqlString = @"SELECT FT_TBL.*
            FROM EquipmentMaintenances AS FT_TBL
                INNER JOIN FREETEXTTABLE(vw_maintenanceSearch, Search, @param1) AS KEY_TBL ON FT_TBL.EquipmentMaintenanceID = KEY_TBL.[KEY]
                WHERE FT_TBL.Status = 1  
                            ORDER BY RANK DESC,  FT_TBL.EquipmentMaintenanceID DESC OFFSET @p2 ROWS FETCH NEXT @p3 ROWS ONLY";
        
        
               var sqlCountString = @"SELECT COUNT(1)
        FROM EquipmentMaintenances AS FT_TBL
            INNER JOIN FREETEXTTABLE(vw_maintenanceSearch, Search, @param1) AS KEY_TBL ON FT_TBL.EquipmentMaintenanceID = KEY_TBL.[KEY]
            WHERE FT_TBL.Status = 1  
                        ";
        
        //step 4 run your queries c# doesn't like the reusing of parameters so create 2 (e.g Kevin) so your results will run correctly.
                    var main = _db.Database.SqlQuery<EquipmentMaintenance>(sqlString, parm1, pageParm, pageSizeParm).ToList();
                    var count = _db.Database.SqlQuery<int>(sqlCountString, parm2).FirstOrDefault();
        
        //step 5 created your paged object - I'm using x.pagedlist
                    var paged = new StaticPagedList<EquipmentMaintenance>(main, pageNumber, pageSize, count);
        

        显然,您现在将其传递回您的视图或其他功能以进行显示。

        【讨论】:

          猜你喜欢
          • 2017-10-17
          • 1970-01-01
          • 2011-12-11
          • 2011-09-11
          • 1970-01-01
          • 2019-04-10
          • 2012-06-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多