Database First Validation
Asked Answered
T

2

6

I have an auto-generated Entity Framework model. It was generated using a database first approach. The mid_initial column has a database defined constraint that limits the column to a maximum length of 3 characters.

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

When I try and create a model with a mid_initial greater than 3 characters, a invalid state, ModelState.IsValid is returning true. Because of this db.SaveChanges is then called, which then raises 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);
    }
}

Why is the ModelState.IsValid method returning true? It would seem that my model is not aware of the maximum length constraint. How do I make it aware?

Tomekatomes answered 30/7, 2013 at 15:32 Comment(0)
I
5

EF db-first can't infer constraints from database.

Use the MaxLenght data annotation attribute:

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

Note: this class is a auto generated class and every time you update and save your model (.EDMX file), this code will be overwritten and you'll loose your attributes.

To avoid that, you should extend your classes with some partial classes with the same name and same namespace as your auto-generated classes. If you need examples to show you how, tell me to put it in answer.

Incrust answered 31/7, 2013 at 14:13 Comment(1)
Close... But, as I understand, it wouldn't work. Compiler will say: "Error 2 The type 'Registrant' already contains a definition for 'mid_initial'...). Need to mark class Registrant with MetadataType attribute and create another class for validation. #25723366Spirt
L
3

MVC is EF-agnostic, and as such doesn't implicitly attempt to validate the model using EF validation to populate its ModelState.

You have four basic solutions I can think of right now:

  • Hook them up yourself, for example using MVC filters, DbContext.GetValidationErrors and ModelState.
  • Find and use third-party code that does this already.
  • Validate the code separately using facilities that MVC can use, for example using DataAnnotations. You may try to generate them automatically by modifying the EF T4 template. Note that this is still technically redundant (the code will be validated twice, once by MVC, once by EF).
  • Submit a patch for MVC so that it can support EF explicitly (as a soft dependency) and make it all just work (both projects are open source) -- or downvote me because they already did so and I never knew it.
Lauralee answered 30/7, 2013 at 16:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.