2

我正在使用实体框架,我想验证我的模型。实体框架验证无例外

示例服务:

var user = _userRepository.GetUser(...); 
var order = user.MakeOrder();    //<- this is some business logic in Rich Domain Model 
_userRepository.Update(user); 
_orderRepository.Add(order); 

数据库操作可以抛出DbEntityValidationException。我能赶上它,并做了一些工作呈现错误用户:

try 
{ 
    _userRepository.Update(user); 
    _orderRepository.Add(order); 
} 
catch(DbEntityValidationException ex) 
{ 
    var error = ex.EntityValidationErrors(); 
    //Pass errors to Controller 
} 

但我知道,那异常缓慢。有没有办法做到没有例外的相同的东西(例如某种返回值)以获得更好的性能?

+0

做你的HTML文件'cshtml'? – Lucas

+0

@ I'bBlueDaBaDee,是 –

+1

那么,你想避免例外,所以如果你的错误说,缺少必填字段,然后确保这些被捕获客户端。 –

回答

0

您可以使用DbContext.SaveChanges内部使用的相同方法。它是公开的 - DbContext.GetValidationErrors

验证跟踪的实体并返回包含验证结果的DbEntityValidationResult集合。

当然,你应该以某种方式暴露你的存储库。

P.S.但是请注意,实际上这可能会导致更糟的性能,因为SaveChanges会再次这样做(并且注意,这种方法包括DetectChanges调用,如备注中所述),因此,由于验证错误应该是例外,所以最好处理它们作为例外情况,即它在你的原始代码中。

-1

我会建议在尝试保存到数据库之前使用构建模型验证。

本示例来自asp.net mvc模板中的构建登录功能。

public class LoginViewModel 
{ 
    [Required] 
    [Display(Name = "Email")] 
    [EmailAddress] 
    public string Email { get; set; } 

    [Required] 
    [DataType(DataType.Password)] 
    [Display(Name = "Password")] 
    public string Password { get; set; } 

    [Display(Name = "Remember me?")] 
    public bool RememberMe { get; set; } 
} 

然后在控制器:

[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) 
    { 
     if (!ModelState.IsValid) 
     { 
      return View(model); 
     } 

     // This doesn't count login failures towards account lockout 
     // To enable password failures to trigger account lockout, change to shouldLockout: true 
     var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); 
     switch (result) 
     { 
      case SignInStatus.Success: 
       return RedirectToLocal(returnUrl); 
      case SignInStatus.LockedOut: 
       return View("Lockout"); 
      case SignInStatus.RequiresVerification: 
       return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
      case SignInStatus.Failure: 
      default: 
       ModelState.AddModelError("", "Invalid login attempt."); 
       return View(model); 
     } 
    } 

并在视图:

@using WebApplication1.Models 
@model LoginViewModel 
@{ 
    ViewBag.Title = "Log in"; 
} 

<h2>@ViewBag.Title.</h2> 
<div class="row"> 
    <div class="col-md-8"> 
     <section id="loginForm"> 
      @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 
      { 
       @Html.AntiForgeryToken() 
       <h4>Use a local account to log in.</h4> 
       <hr /> 
       @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
       <div class="form-group"> 
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 
        <div class="col-md-10"> 
         @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 
         @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 
        <div class="col-md-10"> 
         @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 
         @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        <div class="col-md-offset-2 col-md-10"> 
         <div class="checkbox"> 
          @Html.CheckBoxFor(m => m.RememberMe) 
          @Html.LabelFor(m => m.RememberMe) 
         </div> 
        </div> 
       </div> 
       <div class="form-group"> 
        <div class="col-md-offset-2 col-md-10"> 
         <input type="submit" value="Log in" class="btn btn-default" /> 
        </div> 
       </div> 
       <p> 
        @Html.ActionLink("Register as a new user", "Register") 
       </p> 
       @* Enable this once you have account confirmation enabled for password reset functionality 
        <p> 
         @Html.ActionLink("Forgot your password?", "ForgotPassword") 
        </p>*@ 
      } 
     </section> 
    </div> 
    <div class="col-md-4"> 
     <section id="socialLoginForm"> 
      @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl }) 
     </section> 
    </div> 
</div> 

的HTML辅助方法,ValidationMessageFor将使用在显示注释文本,告知什么是错的。

+0

尽管此链接可能回答问题,但最好在此处包含答案的重要部分并提供供参考的链接。如果链接页面更改,则仅链接答案可能会失效。 - [来自评论](/ review/low-quality-posts/13653732) – tarzanbappa

+0

我知道。我在上床的路上打了电话。今天晚些时候我会在休息时间编辑答案。 –

2

1)你必须实现模型IValidatableObject接口,那么在验证方法

Your Model

2-)使用ModelState.IsValid属性来定义的验证规则。无需try catch块

Your Api

3-)添加验证消息块页面元素

ClientSideValitaion

详情

http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3

附加

您可以使用流利的验证 https://fluentvalidation.codeplex.com/wikipage?title=mvc

基本例如http://www.jerriepelser.com/blog/using-fluent-validation-with-asp-net-mvc-part-1-the-basics