I'm doing code-first development with Entity Framework 4.3 and it doesn't seem like it's possible to express a CHECK constraint via attribute annotations or, well, any other means. I see that EF 5.0 will be adding support for checking enumerations, but that's not exactly what I'm after here.
To give a simplified example, I'd like to validate that all Person
objects have a first name of either "Bob" or "Harry" and are either 5, 10 or 30 years old.
public class Person
{
[Required]
[Check("Bob", "Harry")] //yes, this attribute is imaginary
public string FirstName { get; set; }
[Required, Check(5, 30, 50)] //check is still imaginary
public int Age { get; set; }
}
I can run an alter script to add these constraints after the fact and I can roll my own check attribute to perform validations, but is there a way I'm missing to actually express non-enumerated CHECK constraints in Entity Framework?
The CHECK constraint is used to limit the value range that can be placed in a column. If you define a CHECK constraint on a column it will allow only certain values for this column. If you define a CHECK constraint on a table it can limit the values in certain columns based on values in other columns in the row.
You can specify CHECK constraints at the column or table level and can reference other columns within the table. Internally, all column-level CHECK constraints are converted to table-level constraints so they can be handled consistently.
A check constraint is a rule that specifies the values that are allowed in one or more columns of every row of a base table. For example, you can define a check constraint to ensure that all values in a column that contains ages are positive numbers.
Limitations of CHECK Constraints CHECK constraints reject values that evaluate to FALSE. Because null values evaluate to UNKNOWN, their presence in expressions may override a constraint.
I've been wanting to put Check constraints in, and while there are a couple of ways to do it like the answer given here by M.Babcock and using the ExecuteSql in the Initializer to add constraints to the database manually.
But I think the easiest method is to use a RegularExpression
annotation, so in your example you'd go:
public class Person
{
[Required]
[RegularExpression(@"Bob|Harry")]
public string FirstName { get; set; }
[Required, RegularExpression(@"5|30|50")]
public int Age { get; set; }
}
You could write one yourself (untested):
public class CheckAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
{
object[] ValidValues;
public CheckAttribute<T>(params T[] validValues)
{
ValidValues = validValues;
}
public override bool IsValid(object value)
{
return ValidValues.FirstOrDefault(v => v.Equals(value)) != null;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With