数据库优先验证

时间:2013-07-30 15:32:58

标签: entity-framework ef-database-first

我有一个自动生成的Entity Framework模型。它是使用数据库第一种方法生成的。 mid_initial列具有数据库定义的约束,该列将列限制为最多3个字符的长度。

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Agency.DataAccess.RegistrationModel
{
    using System;
    using System.Collections.Generic;

    public partial class Registrant
    {
        public Registrant()
        {
        }

        public int id { get; set; }
        public string fname { get; set; }
        public string mid_initial { get; set; }
        public string lname { get; set; }
    }
}

当我尝试创建一个mid_initial大于3个字符的模型时,状态无效,ModelState.IsValid返回true。因此,db.SaveChanges会被调用,然后会引发DbEntityValidationException

[HttpPost]
public ActionResult Create(Registrant registrant)
{    
    try
    {
        if (ModelState.IsValid)
        {
            Debug.WriteLine("Entity was valid.");
            db.Registrants.Add(registrant);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View("Create", registrant);
    }
    catch (DbEntityValidationException e)
    {
        foreach (var eve in e.EntityValidationErrors)
        {
            Debug.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                eve.Entry.Entity.GetType().Name, eve.Entry.State);
            foreach (var ve in eve.ValidationErrors)
            {
                Debug.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                    ve.PropertyName, ve.ErrorMessage);
            }
        }
        return View(registrant);
    }
}

为什么ModelState.IsValid方法返回true?我的模型似乎并不知道最大长度约束。我如何让它知道?

2 个答案:

答案 0 :(得分:5)

EF db-first无法从数据库中推断出约束。

使用MaxLenght数据注释属性:

public partial class Registrant
{
    public Registrant()
    {
    }

    public int id { get; set; }
    public string fname { get; set; }
    [MaxLength(3, ErrorMessage = "")]
    public string mid_initial { get; set; }
    public string lname { get; set; }
}

注意:此类是一个自动生成的类,每次更新和保存模型(.EDMX文件)时,此代码都将被覆盖,您将丢失属性。

为避免这种情况,您应该使用与自动生成的类具有相同名称和相同名称空间的某些部分类来扩展您的类。如果您需要示例向您展示如何,请告诉我将其作为答案。

答案 1 :(得分:3)

MVC与EF无关,因此不会隐式尝试使用EF验证来验证模型以填充其ModelState。

您现在可以想到四种基本解决方案:

  • 自己连接它们,例如使用MVC过滤器,DbContext.GetValidationErrors和ModelState。
  • 查找并使用已经执行此操作的第三方代码。
  • 使用MVC可以使用的工具单独验证代码,例如使用DataAnnotations。您可以尝试通过修改EF T4模板自动生成它们。请注意,这在技术上仍然是冗余的(代码将被验证两次,一次由MVC验证,一次由EF验证)。
  • 为MVC提交一个补丁,以便它可以显式支持EF(作为 soft 依赖关系)并使其完全正常工作(两个项目都是开源的) - 或者因为他们已经做了所以所以,我从来不知道。