实体框架中的异常处理

时间:2013-11-16 05:19:10

标签: c# asp.net entity-framework c#-4.0

我有一个表单,它有一些字段并与数据库有关系。我正在使用实体框架我想在sql server发送错误消息之前处理异常。例如,当用户在sql server处理它之前在数字字段win或web应用程序处理异常中输入字符串值时。我编写了这段代码,但它并不适用于所有异常。例如,如果字段为空或具有无效类型,则表示输入字符串的格式不正确。

 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);
                }
             }
        } 

3 个答案:

答案 0 :(得分:7)

您应首先在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

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

答案 1 :(得分:4)

不应该捕获Exception,而应该捕获SqlException。

SqlException有一个可以使用的数字属性:

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

答案 2 :(得分:0)

您应该做的是找到适合您的解决方案模型的架构。一般来说,我会在创建上下文之前进行验证。如果您需要在应用程序中进行更多验证,可能需要为此目的创建验证层。

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;
            }
        }
    }
}

希望该示例使验证逻辑的架构更加清晰。