如何处理存储过程的错误在mvc控制器

本文关键字:错误 mvc 控制器 存储过程 何处理 处理 | 更新日期: 2023-09-27 18:01:28

我正在使用数据库优先方法开发asp.net mvc站点。

我有一个像这样的简单存储过程:

ALTER PROCEDURE [dbo].[ins_item]
    -- Add the parameters for the stored procedure here
    -- item supplied must be in the reference db
    @item varchar(50)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    -- Insert statements for procedure here
    select item 
    from reference.dbo.all_items 
    where item_name = @item
    if @@ROWCOUNT !=1
    begin
        raiserror('supplied item is not found in the master item list.', 11,1)
            return -1
    end
    --Now you know the item is in the reference, insert and handle any errors
END

当我在SQL Server Management Studio中执行此操作时,参考数据库中不存在一个项目,我得到了预期的错误:

消息50000,级别11,状态1,过程ins_item,行xx
提供的物品在主物品列表中找不到。

在我的asp.net mvc应用程序中,我将这个存储过程导入到我的模型中,在我的一个控制器中,我有以下代码:

public ActionResult Create(item item)
{
    if (ModelState.IsValid)
    {
        try
        {
            var insertresult =  db.ins_item(item.item1);
            db.SaveChanges();
        }
        catch (Exception e)
        {
            ViewBag.error = e;
        }
        return RedirectToAction("Index");
    }
    return View(item);
}

db.ins_item看起来像这样在我的模型的数据库上下文,从DbContext类继承:

public virtual ObjectResult<string> ins_item(string item)
{
    var itemParameter = item!= null ?
                new ObjectParameter("item", item) :
                new ObjectParameter("item", typeof(string));
    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<string>("ins_item", itemParameter);
}

问题是,当执行此操作时,我没有得到异常。如何捕获存储过程在上述控制器操作中返回的raiserror ?

如何处理存储过程的错误在mvc控制器

我不使用ObjectContext但DataContext这是推荐的方式。为了获得这些消息,您需要添加以下内容:

var sqlConnection = dbContext.Database.Connection as SqlConnection;
if (sqlConnection != null)
{
    sqlConnection.InfoMessage += InfoMessageEventHandler;
}
private void InfoMessageEventHandler(object sender, SqlInfoMessageEventArgs e)
{
    // code to save error or warning message 
}

考虑到这个事件是在存储过程结束时触发的,所以你不会得到实时通知。

重要的是要强调,这不是作为异常管理的,这就是为什么我们需要显式订阅InfoMessage事件。

另一方面,您可以使用DbContext而不是ObjectContext(旧的方式)来执行存储过程。例如:

dbContext.Database.CommandTimeout = 240;
return dbContext.Database.SqlQuery<string>("spName {0}", value);
可以传递SqlParameters列表,而不是value。