C # Entity Framework: validating data between add to context and saveChanges ()

I have a simple script using Entity Framework in C #. I have an Entity message:

public class Post
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

In my PostManager, I have the following methods:

public int AddPost(string name, string description)
    {
        var post = new Post() { Name = name, Description = description };

        using (var db = new DbContext())
        {
          var res = db.Posts.Add(post);
          res.Validate();
          db.SaveChanges();
          return res.Id;
        }
    }

    public void UpdatePost(int postId, string newName, string newDescription)
    {
        using (var db = new DbContext())
        {
            var data = (from post in db.Posts.AsEnumerable()
                where post.Id == postId
                select post).FirstOrDefault();

            data.Name = newName;
            data.Description = newDescription;
            data.Validate();
            db.SaveChanges();
        }
    }

The validate () method belongs to the class:

public static class Validator
{
    public static void Validate(this Post post)
    {
        if ( // some control)
            throw new someException();
    }

I call the validate method before savechanges (), but after adding the object to the context. What is the best practice for validating data in this simple scenario? Better check the arguments? What happens to the post object if the validate method throws an exception after adding the object to the context?

UPDATE:

I need to throw a custom set of exceptions depending on the data validation error.

+4
source share
6 answers

, Data Annotation, @Micky . .

using System.ComponentModel.DataAnnotations;
// Your class
public class Post
{
    [Required]
    public int Id { get; set; }
    [Required,MaxLength(50)]
    public string Name { get; set; }
    [Required,MinLength(15),MyCustomCheck] // << Here is your custom validator
    public string Description { get; set; }
}

// Your factory methods
public class MyFactory() {
     public bool AddPost() {
     var post = new Post() { Id = 1, Name = null, Description = "This is my test post"};
        try {
            using (var db = new DbContext()) {
                db.Posts.Add(post);
                db.SaveChanges();
                return true;
            }
        } catch(System.Data.Entity.Validation.DbEntityValidationException e) {
            Console.WriteLine("Something went wrong....");
        } catch(MyCustomException e) {
            Console.WriteLine(" a Custom Exception was triggered from a custom data annotation...");
        }
        return false;

     }
}

// The custom attribute
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class MyCustomCheckAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
        {
          if (value instanceof string) {
                throw new MyCustomException("The custom exception was just triggered....")
          } else {
            return true;
          }
        }
}

// Your custom exception
public class MyCustomException : Exception() {}

. : DbEntityValidationException : https://msdn.microsoft.com/en-us/library/system.data.entity.validation.dbentityvalidationexception(v=vs.113).aspx

http://www.entityframeworktutorial.net/code-first/dataannotation-in-code-first.aspx

(): https://msdn.microsoft.com/en-us/library/cc668224.aspx

+2

( ) , ( , EF ), (EF /) .

:

  • , , .
  • . , , .
  • . , .
  • . : ", int?" .
  • . , , . , , . , , , , , .. SOLID OOP.

, "" , () ORM , , imo.

:

public class Post
{
    protected Post() // this constructor is only for EF proxy creation
    {
    }

    public Post(string name, string description)
    {
        if (/* validation check, inline or delegate */)
            throw new ArgumentException();

        Name = name;
        Description = description;
    }

    public int Id { get; private set; }
    public string Name { get; private set; }
    public string Description { get; private set; }
}

PostManager :

using (var db = new DbContext())
{
    var post = new Post(name, description); // possibly try-catch here
    db.Posts.Add(post);
    db.SaveChanges();
    return post.Id;
}

/ , factory, .

, , API, , , , , .

+2

, .NET System.ComponentModel.DataAnnotations .

(DA) . , DA API ORM, Entity Framework, , DA, , ; WCF; ASP.NET MVC WPF.

Muppet .

  • Name 50.

  • Scaryness int, {0... 100}.

  • Email , .

:

public class Muppet
{
    [Required]
    [StringLength(50)]
    public string Name {get; set;}  

    public Color Color {get; set; }

    [Range(0,100)]
    public int Scaryness {get; set; }

    [MyCustomEmailValidator]
    public string Email {get;set; }
}

customException, . ?

, . ( , EF ), :

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

.
.
.
Post post = ... // fill it in
Validator.Validate(post);

public static class Validator
{
    public static void Validate(this Post post)
    {
        // uses the extension method GetValidationErrors defined below
        if (post.GetValidationErrors().Any())
        {
            throw new MyCustomException();
        }
     }
}


public static class ValidationHelpers
{

    public static IEnumerable<ValidationResult> GetValidationErrors(this object obj)
    {
        var validationResults = new List<ValidationResult>();
        var context = new ValidationContext(obj, null, null);
        Validator.TryValidateObject(obj, context, validationResults, true);
        return validationResults;
    }
.
.
.

, :

    /// <summary>
    /// Gets the validation error messages for column.
    /// </summary>
    /// <param name="obj">The object.</param>
    /// <returns></returns>
    public static string GetValidationErrorMessages(this object obj)
    {
        var error = "";

        var errors = obj.GetValidationErrors();
        var validationResults = errors as ValidationResult[] ?? errors.ToArray();
        if (!validationResults.Any())
        {
            return error;
        }

        foreach (var ee in validationResults)
        {
            foreach (var n in ee.MemberNames)
            {
                error += ee + "; ";
            }
        }

        return error;
    }

, , EF, , .

+1

:

  • - jQuery Unobtrusive Validation
  • - - -. - OnSave .

, , , .

0

:

    public int AddPost(string name, string description)
    {
        var post = new Post() { Name = name, Description = description };
        if(res.Validate())
        {
            using (var db = new DbContext())
            {
              var res = db.Posts.Add(post);
              db.SaveChanges();
              return res.Id;
            }
        }
        else
            return -1; //if not success
   }


    public static bool Validate(this Post post)
    {
        bool isValid=false;
        //validate post and change isValid to true if success
        if(isvalid)
            return true;
        }
        else
            return false;
    }
0

After adding data to the DbContext and before calling SaveChanges (), you can call the GetValidationErrors () method of DbContext and check its quantity to check if there are any errors. You can additionally list all errors and get information about errors for each of them. I have included error conversion from ICollection to string in the GetValidationErrorsString () extension method.

 if (db.GetValidationErrors().Count() > 0)
 {
    var errorString = db.GetValidationErrorsString();
 }


 public static string GetValidationErrorsString(this DbContext dbContext)
{
    var validationErrors = dbContext.GetValidationErrors();
    string errorString = string.Empty;
    foreach (var error in validationErrors)
    {

        foreach (var innerError in error.ValidationErrors)
        {
            errorString += string.Format("Property: {0}, Error: {1}<br/>", innerError.PropertyName, innerError.ErrorMessage);
        }
    }
    return errorString;
}
0
source

Source: https://habr.com/ru/post/1625331/


All Articles