Entity Framework中的异常处理

10

我有一个表单,它有一些字段并与数据库相关。我正在使用Entity Framework,我想在SQL Server发送错误消息之前处理异常。例如,当用户在数字字段中输入字符串值时,Win或Web应用程序会在SQL Server处理异常之前处理异常。我编写了这段代码,但它并不能处理所有异常。例如,如果字段为空或类型无效,则显示输入字符串不在正确的格式中。

 using (var context  = new entityTestEntities2())
        {
            try
            {
                int stNumber = Convert.ToInt32(textBox2.Text);
                var allCustomers = context.setcust(null, stNumber);
            }
            catch(Exception ex)
            {
                if (ex.Message.Contains("correct format"))
                { 
                int x= System.Runtime.InteropServices.Marshal.GetExceptionCode();
                     MessageBox.Show("error number"+x.ToString()+ex.Message);
                }
             }
        } 

我建议使用Integer.TryParse来从文本框中获取输入。 - OneFineDay
我的问题很普遍,只是一个例子(整数或空字段)。 - heavy
1
UI长什么样子?我们最近经常使用MVC3,我们将使用属性构建数据模型和/或使用不显眼的JavaScript验证。我认为您会希望在UI更接近的位置进行验证,而不是让它调用数据库,特别是在Web环境中。 - Jake Hargus
我在Web应用程序中使用JavaScript完成了它,但我想生成核心并在核心中放置异常处理。我想找到一个解决方案。 - heavy
EF中的验证:http://msdn.microsoft.com/en-gb/data/gg193959.aspx MVC使用实体上的数据注释来支持jQuery不显眼验证。https://dev59.com/gWgu5IYBdhLWcg3wJT9I - Colin
3个回答

15

您应该先在UI上进行验证,然后处理与Entity Framework相关的特定错误。

创建一个模型并使用数据注释:

using System.ComponentModel.DataAnnotations;
public class YourViewModel
    {
        [Required]
        [Range(0, 15, ErrorMessage = "Can only be between 0 .. 15")]
        public int stNumber { get; set; }
    }
在你的控制器中将模型返回给视图:
var model = new YourViewModel();
return View(model);

通过将模型添加到视图并使用一些标签助手,将您的文本框绑定到模型:

@using YourProject.WebUI.Models
@model YourViewModel  

@Html.TextBoxFor(m => m.stNumber )
@Html.ValidationMessageFor(m => m.stNumber )
现在,当有人尝试输入非数字或超出范围的数字时,在错误数据被发送回控制器之前,会向用户显示错误信息。 要处理Entity Framework异常,请使用try catch:
        try
        {
            var entity = context.yourEntity.FirstOrDefault(o => o.Id == custId);

            if (entity == null) return false;
            entity.value= stNumber;
            entity.ModifiedBy = userId;
            entity.ModifiedDate = DateTime.Now;
            Db.SaveChanges();
            return true;
        }
        catch (DbUpdateException Ex)
        {
            Console.WriteLine(Ex.InnerException.Message);
            return false;
        }

其他异常类型包括:

DbUpdateException

向数据库发送更新时出现错误。

DbUpdateConcurrencyException

数据库命令未影响预期的行数。通常这表示存在乐观锁冲突;也就是说,自查询后数据库中的某一行已被更改。

DbEntityValidationException

由于实体属性值的验证失败,保存操作被中止。

NotSupportedException

尝试使用不受支持的行为,比如在同一上下文实例上同时执行多个异步命令。

ObjectDisposedException

上下文或连接已被释放。

InvalidOperationException

在向数据库发送命令之前或之后,在上下文中处理实体时出现了一些错误。


4

与其捕获异常,你应该捕获SqlException。

SqlException有一个可用的number属性:

catch (SqlException e)
{
   MessageBox.Show("Error number: "+e.Number + " - " + e.Message);
}

4
你需要做的是找到一个适合你解决方案模型的架构。通常情况下,在创建上下文之前进行验证。如果你的应用程序需要更多的验证,你可能需要为此创建一个验证层。
public class RuleViolation
{
    public string Property {get; set;}
    public string Message {get; set;}
}

public class Program
{
    public static List<RuleViolation> GetRuleViolations(string[] parameters)
    {
        List<RuleViolation> validations = new List<RuleViolation>();

        if(!int.TryParse(parameters[0], out new Int32()))
        {
            validations.Add(new RuleViolation{Message ="Input1 must be integer.", Property = "input1"});
        }
        //more validation

        return validations;
    }

    public static void Main(string[] parameters)
    {
        var validations = GetRuleViolations(parameters);

        if(validations.Any())
        {
            validations.ForEach(x=> Console.WriteLine(x.Message));
            return;
        }

        int input1 = int.Parse(parameters[0]);

        //after all your business logic are ok, then you can go to persistence layer to hit the database.
        using (var context  = new entityTestEntities2())
        {
            try
            {
                var allCustomers = context.setcust(null, input1);
            }
            catch(SqlException exc)
            {
                //here you might still get some exceptions but not about validation.

                ExceptionManager.Log(exc);

                //sometimes you may want to throw the exception to upper layers for handle it better over there!
                throw;
            }
        }
    }
}

希望这个例子可以更清晰地说明关于验证逻辑的架构。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接