如何在打开的事务中执行自定义类型的存储过程?

时间:2016-06-23 06:54:40

标签: c# sql-server entity-framework ado.net

我已从Entity Framework上下文中打开事务,需要执行sp_ComplexTypedProc过程,该过程接受自定义类型参数并返回(选择)数据

CREATE PROCEDURE [dbo].[sp_ComplexTypedProc]
@param1 IDSource readonly 
AS
BEGIN
SELECT 
Person.Name as Name
Person.Gender as Gender
Person.BirthDate as BirthDate
...
from dbo.Persons Person
END

我尝试从C#代码执行过程:

    var currentTransaction = dbContext.Database.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
    .....

    var command = currentTransaction.UnderlyingTransaction.Connection.CreateCommand();
    command.CommandText = "sp_ComplexTypedProc";
    command.CommandType = System.Data.CommandType.StoredProcedure;

    List<Guid> IdSource = new List<Guid>()
    { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };

    SqlParameter sqlParameter = new SqlParameter();
    sqlParameter.TypeName = "IDSource"; //IDSource is my custom type
    sqlParameter.ParameterName = "@param1";
    sqlParameter.Value = IdSource;

    command.Parameters.Add(sqlParameter);

    command.ExecuteReader();
    .....
    currentTransaction.Commit();

但它抛出以下异常:

  

当分配给命令的连接处于挂起的本地事务中时,ExecuteReader要求该命令具有事务。该命令的Transaction属性尚未初始化。

有没有办法在打开的交易中执行sp_ComplexTypedProc程序?

1 个答案:

答案 0 :(得分:0)

使用TransactionalBehavior和ExecuteSqlCommand,您可以定义命令如何附加到trasncation: https://msdn.microsoft.com/en-us/library/system.data.entity.transactionalbehavior(v=vs.113).aspx &#34;从EF6 Database.ExecuteSqlCommand()开始,默认情况下将命令包装在事务中(如果尚未存在)。 &#34;

ExecuteNonQuery示例:

  using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot)) 
               { 
                   try 
                   { 
                       var sqlCommand = new SqlCommand(); 
                       sqlCommand.Connection = conn; 
                       sqlCommand.Transaction = sqlTxn; 
                       sqlCommand.CommandText = 
                           @"UPDATE Blogs SET Rating = 5" + 
                            " WHERE Name LIKE '%Entity Framework%'"; 
                       sqlCommand.ExecuteNonQuery(); 

                       using (var context =  
                         new BloggingContext(conn, contextOwnsConnection: false)) 
                        { 
                            context.Database.UseTransaction(sqlTxn); 

                            var query =  context.Posts.Where(p => p.Blog.Rating >= 5); 
                            foreach (var post in query) 
                            { 
                                post.Title += "[Cool Blog]"; 
                            } 
                           context.SaveChanges(); 
                        } 

                        sqlTxn.Commit(); 
                    } 
                    catch (Exception) 
                    { 
                        sqlTxn.Rollback(); 
                    } 
                }