0

I would like to make a constraint that will assure that Beginning is less than End. I use Entity Framework, as far as I know it cannot be done by annotations. Can it be done in OnModelCreating method?

 public class Duty {
        public int Id { get; set; }
        public virtual Employee Employee { get; set; }
        public virtual Store Store { get; set; }
        public DateTime Beginning { get; set; }
        public DateTime End { get; set; }
    }

4 Answers4

2
    public class SomeEntity
    {
        [MustBeLessThanDate(nameof(End))]
        public DateTime Beginning { get; set; }

        public DateTime End { get; set; }
    }

    public class MustBeLessThanDateAttribute : ValidationAttribute
    {
        private readonly string _otherPropertyName;

        public MustBeLessThanDateAttribute(string otherPropertyName)
        {
            _otherPropertyName = otherPropertyName;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var containerType = validationContext.ObjectInstance.GetType();

            var field = containerType.GetProperty(_otherPropertyName);

            var otherValue = (DateTime) field.GetValue(validationContext.ObjectInstance, null);

            var thisValue = (DateTime) value;

            return thisValue < otherValue
                ? ValidationResult.Success
                : new ValidationResult("Value is not less than other value");
        }
    }
Timothy Stepanski
  • 1,186
  • 7
  • 21
  • This looks great! Thanks! – user6445699 Jun 09 '16 at 13:53
  • This solution looks the best for me but are there any advantagers over the Darshan Patel's solution respecting mapping by Entity Framework? – user6445699 Jun 09 '16 at 14:11
  • Darshan is violating the core principals of what a POCO is as well as separation of concerns. His code is not recyclable. Also, if you switch ORM's, some override the getters and setters on POCO's. – Timothy Stepanski Jun 09 '16 at 14:13
  • @Timothy Stepanski: I agree and also would state that your code also uses reusability which every dev should strive for encapsulation and reuse. Yours you can reuse as well and fits the one principle rule. Plus you did it with an attribute too which is nice as well. – djangojazz Jun 09 '16 at 15:00
  • @djangojazz Thank you, I appreciate that. – Timothy Stepanski Jun 09 '16 at 15:01
1

You can use custom validation, by deriving from ValidationAttribute class, which has IsValid method which you can override. You can create this class in your viewModel, then apply created attribute on your enddate.

Krtti
  • 62
  • 10
0

An answer for the same is here.

OR

Try exploring FluentValidation.

It uses a fluent interface and lambda expressions for building validation rules.

From the documentation, you can include it via NuGet as -

Install-Package FluentValidation

Implementing a constraint is as simple as:

using FluentValidation;

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

Try it out. (I've not customized the example to your needs, you might have to read the in depth documentation here.)

Community
  • 1
  • 1
Sunny R Gupta
  • 5,026
  • 1
  • 31
  • 40
0

Why are you not use condition in your property. something like this....

public int Id { get; set; }
public virtual Employee Employee { get; set; }
public virtual Store Store { get; set; }
public DateTime Beginning { get; set; }

private DateTime _end;
public DateTime End {
    get
    {
        return _end;
    }
    set
    {
        if (value < Beginning)
        {
            throw new Exception("End date can not be less than beginning date.");
        }
        _end = value;
    }
}

But don't forget to assign your beginning date before assign end date

Gabor
  • 3,021
  • 1
  • 11
  • 20
Darshan Faldu
  • 1,471
  • 2
  • 15
  • 32