使用实体框架执行存储过程

时间:2013-10-22 14:00:24

标签: entity-framework c#-4.0 stored-procedures repository-pattern

我们目前正在开发一个内部系统,使用存储库模式和Entity Framework 5作为我们的ORM。

我们在数据库中有一堆存储过程,我们称之为。其中一些程序具有类似的参数名称。因此,当我们调用执行存储过程时,如下所示:

DbContext.Database.SqlQuery<ReturnType>(query, parameters)

在第二次调用具有类似参数名称的另一个过程时,生成的枚举失败,说:

  

用户代码未处理ArgumentException:SqlParameter已被另一个SqlParameterCollection包含。

我们已经尝试将所有SqlParameters放入我们循环的集合中,并将集合中的所有项目归零,但这也失败了....光荣地。

有没有办法在此堆栈跟踪中访问和操作Object数组?

  

at System.Data.SqlClient.SqlParameterCollection.Validate(Int32 index,Object value)
  在System.Data.SqlClient.SqlParameterCollection.AddRange(数组值)
  在System.Data.Objects.ObjectContext.CreateStoreCommand(String commandText, Object []参数

  at System.Data.Objects.ObjectContext.ExecuteStoreQueryInternal [TElement](String commandText,String entitySetName,MergeOption mergeOption, Object [] parameters

  at System.Data.Objects.ObjectContext.ExecuteStoreQuery [TElement](String commandText, Object [] parameters
  在System.Data.Entity.Internal.InternalContext.ExecuteSqlQuery [TElement](String sql, Object []参数

  在System.Data.Entity.Internal.InternalContext.ExecuteSqlQueryAsIEnumerable [TElement](String sql, Object []参数

  在System.Data.Entity.Internal.InternalContext.ExecuteSqlQuery(类型elementType,String sql,对象[]参数

  在System.Data.Entity.Internal.InternalSqlNonSetQuery.GetEnumerator()
  在System.Data.Entity.Internal.InternalSqlQuery 1.GetEnumerator()
at System.Linq.Enumerable.First[TSource](IEnumerable
1来源)

5 个答案:

答案 0 :(得分:2)

你可以这样做:

List<ReturnType> obj = DbContext.Database.SqlQuery<ReturnType>(query, parameters).ToList();

它将绑定变量obj,之后你可以调用obj你想要多少次没有sqlParameter问题。

答案 1 :(得分:0)

我还没有能够解决这个问题,在内置的SqlQuery方法中的命令对象似乎没有清除sql参数,但是我有一个解决方法。 您可以根据当前连接创建自己的命令 - 但是您将无法轻松映射返回类型。

public void CallStoredProc(string query, List<SqlParameter> parameters)
{
    //this.Database.Connection (this = DBContext)
    System.Data.Common.DbCommand cmd =  this.Database.Connection.CreateCommand();
    cmd.CommandText = query;

    // add params
    foreach (var item in parameters)
    {
        cmd.Parameters.Add(item);
    }

    // execute query (not differed)
    var reader = cmd.ExecuteReader();


    // attempt to read rows
    if (reader.HasRows)
    {
        while (reader.Read())
        {
            // row level data
        }
    }

    // cleanup
    cmd.Parameters.Clear();
    cmd.Dispose();
}

答案 2 :(得分:0)

您是否能够复制参数集合和每个参数,而不是重复使用相同的参数实例?也许在某个地方有一个帮助器方法可以自动为你复制它。

答案 3 :(得分:0)

我找到了一个解决方案,解决了这个问题。存储的proc调用用于实例化将在执行后处理的新DbContext,如下所示。

IEnumerable<ReturnType> Results = null;

using (DbContext NewContext = new PrometheusEntities())
{
    Results = NewContext.Database.SqlQuery<ReturnType>(query, parameters).ToList();    
}    
return Results;

自从采用这种方法以来,我没有遇到任何问题。

答案 4 :(得分:0)

Create Stored Procedure 
 ALTER PROCEDURE [dbo].[sp_GelUserContactDetails]  
  (  
    @Id INT=0,  
    @UserId int=0  
  )  
 AS  
    BEGIN  
SELECT M.Id AS UserID, M.FirstName as Name,M.Designation,M.CompanyName FROM dbo.Flo_MemberShip M  
WHERE ID=@Id 
END  

//创建保存类MyContacts

结果的存储过程
 public class MyContacts  
   {  
    public int UserID { get; set; }  
    public string Designation { get; set; }  
    public string Name { get; set; }  
    public string Organization { get; set; }  
    public string Image { get; set; }  
    public string RequestDate { get; set; }  
    public string IsContact { get; set; }  
   }

这里我正在创建一个名为MyContacts的实体。此处MyContacts属性名称必须与存储过程的select语句的返回列相同。

using (var context = new FLOEntities())  
 {  
   string query = "sp_GelUserContactDetails @Id,@UserId";  
   SqlParameter Id = new SqlParameter("@Id", selfId);  
   SqlParameter UserId = new SqlParameter("@UserId", userId);  
   obj = context.Database.SqlQuery<MyContacts>(query, Id, UserId).FirstOrDefault();  
 }  
return obj;

click here