调用存储过程时,使用Entity Framework处理响应时出错

时间:2017-10-13 17:15:20

标签: c# sql-server entity-framework

使用实体框架时,所提供的方法是如何处理SQL存储过程中的错误。

我有一大堆代码使用数据库上下文和EF来调用存储过程。如果一切都很完美,存储过程将返回一个键列表,告诉我哪些记录被修改。如果存储过程中出现问题,事务将回退,我相信响应类型是一个字符串并导致此错误:

  

数据阅读器有多个字段。多个字段对EDM原语或枚举类型无效。

在进行了挖掘后,我注意到SQL开发人员已将“PRINT:ERROR MESSAGE HERE”语句传回消息,但当前调用不允许这样做,

以下是目前正在进行的通话方式:

var partIdsCreated = context.Database.SqlQuery<int>("EXEC My_SP @FilePath, @FileName", args).ToList();

当前代码期望一个Int列表,如果返回一个字符串,则错误输出上面列出的错误消息,那么使用Entity Framework 6处理从事务中的存储过程返回的错误的最佳方法是什么? ?

1 个答案:

答案 0 :(得分:1)

下面我提供了两种类似的方法来处理SQL Server返回的消息。如评论中所述,两者都涉及在连接上使用InfoMessage事件。

要回答你的问题,我真的不知道将PRINT语句作为错误处理的首选方法,但我也不确定另一种处理输出的方法。

解决方案1:捕获例外

public class DataLoader_01
{
    public int LoadData()
    {
        _infoMessage = null;
        using (var context = new ApplicationDbContext(@"Server=localhost\SQLEXPRESS;Database=StackOverflow;Trusted_Connection=True;"))
        {
            var sqlConnection = (SqlConnection)context.Database.Connection;
            sqlConnection.InfoMessage += InfoMessage;

            try
            {
                var t = context.Database.SqlQuery<int>("EXEC ErrorMessageHandling", new object[] {});
                return t.First();
            }
            catch (EntityCommandExecutionException e)
            {
                if (string.IsNullOrEmpty(_infoMessage))
                {
                    //do some error handling specific to your application
                    throw new ApplicationSpecificException(_infoMessage);
                }
                throw;
            }
        }
    }

    private void InfoMessage(object sender, SqlInfoMessageEventArgs e)
    {
        _infoMessage = e.Message;
    }

    private string _infoMessage;
}

解决方案2:检查字段数

public class DataLoader_02
{
    public int LoadData()
    {
        _infoMessage = null;

        using (var context = new ApplicationDbContext(@"Server=localhost\SQLEXPRESS;Database=StackOverflow;Trusted_Connection=True;"))
        {
            var sqlConnection = (SqlConnection)context.Database.Connection;
            sqlConnection.InfoMessage += InfoMessage;

            var cmd = context.Database.Connection.CreateCommand();
            cmd.CommandText = "[dbo].[SomeProc]";

            try
            {
                context.Database.Connection.Open();

                var reader = cmd.ExecuteReader();

                if (reader.FieldCount == 0)
                {
                    throw new ApplicationSpecificException(_infoMessage);
                }

                var result = ((IObjectContextAdapter)context).ObjectContext.Translate<int>(reader);

                return result.First();
            }
            finally
            {
                context.Database.Connection.Close();
            }
        }
    }

    private void InfoMessage(object sender, SqlInfoMessageEventArgs e)
    {
        _infoMessage = e.Message;
    }

    private string _infoMessage;
}