This post is a follow-up on the post about Validation attributes in Code-First. While validation attributes focus on making sure the data in the model is correct, the attributes listed here instead focus on instructing Entity Framework’s database generation engine how the database should be structured.
Column
Specify what column name to use for this class in the database.
public class Customer
{
[Column("CustomerFirstName")]
public string FirstName { get; set; }
}
ConcurrencyCheck
Mark property as included in a value level optimistic concurrency check. This means that the property will be verified that it hasn’t changed before a new Update or Insert is performed. You need to mark all non-key properties, that you want to check, with this attribute.
public class Customer
{
public int Id { get; set; }
[ConcurrencyCheck]
public string Name { get; set; }
[ConcurrencyCheck]
public int Age { get; set; }
[ConcurrencyCheck]
public string City { get; set; }
}
If you have large tables, this can cause large where clauses also and thus slowing down your queries. This way of performing optimistic concurrency check is therefore not the suggested one. Instead, use the TimeStamp
attribute to simply figure out if the row has been changed or not.
DatabaseGenerated
Indicates that this property is generated by the database (i.e., a TimeStamp
or an automatically increased id) and that EF should leave it. There are three different options to choose from:
None
– no value is generated Identity
– database creates an id when row is inserted Computed
– database calculates a value when a row is inserted or updated
public class Customer
{
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedDate { get; set; }
}
ForeignKey
Used if a linked property and its foreign key id property are named in different ways. If the linked property is named SystemUser
and the foreign key property is named SystemUserId
(with only Id
added at the end), then there’s no need for this attribute. In the example below, these Entity Framework naming conventions are not being followed and the ForeignKey
attribute is needed for the User
property.
public class Customer
{
[Key]
public int CustomerId { get; set; }
public int SystemUserId { get; set; }
[ForeignKey("SystemUserId")]
public virtual SystemUser User { get; set; }
}
InverseProperty
Specify back-reference in relationship when naming logic doesn’t apply. In the example below, the Customer
class refers to SystemUser
as User
. For the SystemUser
to be able to link to the correct property in Customer
, you have to specify the name of the property using the InverseProperty
attribute. If the Customer
class would have referred to the user as SystemUser
, then there wouldn’t be any need for adding this property.
public class Customer
{
[Key]
public int CustomerId { get; set; }
public int SystemUserId { get; set; }
[ForeignKey("SystemUserId")]
public virtual SystemUser User { get; set; }
}
public class SystemUser
{
[Key]
public int SystemUserId { get; set; }
[InverseProperty("User")]
public virtual IEnumerable<Customer> Customers { get; set; }
}
Key
Naming conventions for Entity Framework specify that the default name for the key property should be either Id
or the class name combined with “Id
” as in BlogId
or CustomerId
. If these conventions are used, then Entity Framework will be able to find the key property. But if you want to use a different name for the key of your class, you have to decorate it with the [Key]
attribute, as in the following example.
public class CrmCustomer
{
[Key]
public int CustomerId { get; set; }
}
MaxLength and StringLength
These attributes work for validation purposes, but they will also limit the size of the parameter’s field in the database. Besides the fact that StringLength
also can specify a MinLength
, they are practically identical. The reason why the new MaxLength
attribute was added was because binary data can be stored as well and StringLength
wrongly implies it has to be a string
.
If a string
is used without any size limitations, the database field gets the nvarchar(MAX)
type where MAX
= 4000. However, since nvarchar
is used, the database field only uses the space it needs.
If we want to limit the maximum space used, we can use anyone of MaxLength
and StringLength
.
public class Customer
{
public int Id { get; set; }
[MaxLength(40)]
public string City { get; set; }
[StringLength(40)]
public string County { get; set; }
[MaxLength(40)]
public string Country { get; set; }
}
In the picture below, the max length is set to 40 for all string
s. However, the city field was updated in the model from “no restriction” to [MaxLength(40)]
and that didn’t have any effects on the database structure. This is due to the fact that shrinking the size of a field is potentially problematic and you might end up with lost data. This new size constraint is therefore only used internally in Entity Framework and not in the database storage.
The largest possible length of a string
you can set is determined by the length of an Int32
. To use that value, simply write:
public class Comment
{
[StringLength(Int32.MaxValue)]
public string Text { get; set; }
}
MetadataType
This attribute is not used by Code-first, but rather by Model first where you’re able to add code-first attributes to a model-first created class. You can read more about it here.
NotMapped
Mark class/property as excluded from database storage. This is useful if you have a calculated or concatenated parameter, as in the example below.
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FullName { get { return FirstName + " " + LastName; } }
}
Required
Mark field as required and that it can’t be null
. This is also used as a validation attribute.
public class Customer
{
public int id { get; set; }
[Required]
public int age { get; set; }
}
ScaffoldColumn
Indicates if a column should be included in scaffolding or not.
public class Data
{
public int Id { get; set; }
[ScaffoldColumn(false)]
public int InternalData { get; set; }
}
Table
Specify what table name to use in database.
[Table("CrmSystem_Customer")]
public class Customer
{
[Key]
public int CustomerId { get; set; }
}
TimeStamp
The TimeStamp
attribute is used to enable Optimistic Concurrency Check
in Entity Framework. A good overview on how to implement it can be found here. To use it, just add an extra byte array property to your class marked with the TimeStamp
attribute, as shown here:
public class Customer
{
[Key]
public int CustomerId { get; set; }
[TimeStamp]
public byte[] RowVersion { get; set; }
}
Validation Attributes
The following attributes are described in my post about validation attributes: Compare
, CreditCard
, CustomValidation
, DataType
, Display
, DisplayFormat
, EmailAddress
, EnumDataType
, FileExtensions
, MaxLength
, MembershipPassword
, MinLength
, Phone
, Range
, RegularExpression
, Required
, StringLength
, UIHint
and Url
.
Attributes in DataAnnotations class not included here
Association
DisplayColumn
– Used by DynamicData
to specify what column to display as foreign key label, and how to sort (read more) Editable
– According to the manual, it indicates whether the user should be able to change the field’s value. There is no enforcing in MVC to make sure this is kept and it’s up to the programmer to use it internally. ScaffoldTable
– Used by ASP.NET Dynamic Data to decide whether a table should be scaffolded or not
More Resources
If you want to read more about DataAnnotations
, I suggest the following links: