16 out of 18 rated this helpful - Rate this topic

Code First Data Annotations

Entity Framework
[This page is specific to the latest version of the Entity Framework. The latest version is available as the as the 'Entity Framework'NuGet package. For more information, see Entity Framework Releases and Versioning.]

The System.ComponentModel.DataAnnotations namespace defines attributes that are used to provide additional information about classes and properties. These attributes are consumed by Code First when discovering a conceptual model.

You can use annotations to override the default conventions. For example, you can specify that a specific property is to be used as the primary key. Or you can set the length of a text field, which will override the default.

To use annotations, you must add a reference to EntityFramework.dll and System.ComponentModel.DataAnnotations.dll to your project, and you must add a using (C#) or Imports (Visual Basic) statement for the System.ComponentModel.DataAnnotations namespace to the source file where your model is defined.

noteNote:
Starting with Entity Framework 5.0 Beta 1, the EntityFramework.dll does not contain definitions for data annotations. These definitions were moved to System.ComponentModel.DataAnnotations.dll and are defined in the System.ComponentModel.DataAnnotations.Schema namespace.

Supported Annotations

  • ColumnAttribute specifies the database column name, ordinal, and data type that a property is mapped to.

  • ComplexTypeAttribute is placed on a class to specify that the class is a complex type. Complex types do not have keys and cannot be managed by the Entity Framework apart from the parent object. Use a complex type when you want to organize scalar properties of entity types in a separate type. Then define a property of the complex type on your entity type.

  • ConcurrencyCheckAttribute specifies that a property participates in optimistic concurrency checks. By default, the Entity Framework implements an optimistic concurrency model. This means that locks are not held on data in the data source between when the data is queried and the data is updated. The Entity Framework saves object changes to the database without checking for concurrency. For entities that might experience a high degree of concurrency, we recommend that the entity define a property with the [Timestamp] attribute.

  • DatabaseGeneratedAttribute specifies that the values for a property should be generated by the database. DatabaseGeneratedAttribute takes the DatabaseGeneratedOption enumeration as an argument. The possible values for the DatabaseGeneratedOption are Identity, Computed, or None. Setting the DatabaseGeneratedAttribute on a column to Identity or Computed forces the value for the column to be retrieved from the server as an Identity or Computed value when you call SaveChanges. Identity properties are read from the data source when the type is first saved, but afterward, they are assumed to be unchanged. Computed properties are read every time SaveChanges is called. None indicates that it is not a server generated property. Identity is the default value for integer key properties when working with Code First.

  • ForeignKeyAttribute is placed on a navigation property to specify the property that represents the foreign key of the relationship.

  • InversePropertyAttribute is placed on a navigation property to specify the property that represents the other end of a relationship. You typically need it only if you have multiple relationships between the same types.

    For example, suppose that you define the Person and Book classes, where the Person class contains the ReviewedBooks and AuthoredBooks navigation properties, and the Book class contains the Author and Reviewer navigation properties. You then need to specify Author as the inverse of AuthoredBooks and Reviewer as the inverse of ReviewedBooks.

  • KeyAttribute denotes one or more properties that uniquely identify an entity.

  • MaxLengthAttribute specifies the maximum length of array or string data allowed in a property.

  • MinLengthAttribute specifies the minimum length of array or string data allowed in a property.

  • NotMappedAttribute can be applied to classes or properties. When this attribute is specified, the class or property will not be included in the generated database schema.

  • RequiredAttribute specifies that a value is required. This attribute is ignored on complex and collection navigation properties. When specified on a reference navigation property, it means that the cardinality of the reference is “1” and the foreign key property is non-nullable.

  • StringLengthAttribute specifies the minimum and maximum length of characters that are allowed in a field.

  • TableAttribute is placed on a class to specify the table name to which the class is mapped.

  • TimestampAttribute specifies that this column should be treated as a timestamp column in the database and checked for changes before saving changes to the store. This attribute applies to scalar properties of byte[] type only. Only one TimestampAttribute can be present on an entity.

Map the Primary Key

If your class defines a property whose name is “ID” or “Id”, or a class name followed by “ID” or “Id”, the Entity Framework treats this property as a primary key by convention. This approach works in most common database mapping scenarios, but the Entity Framework provides ways for you to override this convention. To explicitly set a property to be a primary key, you can use the [Key] data annotation.


public class StudentGrade
{
    // Use the KeyAttribute on the EnrollmentID property, 
    // because we want to override primary key conventions.
    [Key]
    public int EnrollmentID { get; set; }
    public decimal? Grade { get; set; }
}

Switching off identity for numeric primary keys

The following example sets the CourseID property to System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None to indicate that the value will not be generated by the database.

public class Course
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }
}

Map the Table-per-Type Inheritance

When the classes participate in an inheritance hierarchy, Code First uses the Table-per-Hierarchy strategy when generating the database schema by default. This means that the properties of all the classes in the hierarchy are mapped to one table (by default the table name will be the same as the base class). If you want to use the Table-per-Type strategy you must explicitly map the derived classes to separate tables. The following code specifies that the OnlineCourse class should be mapped to a separate table, called OnlineCourse.


public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }
}

[Table("OnlineCourse")]
public partial class OnlineCourse : Course
{
    public string URL { get; set; }
}

Map a One to Zero or One Relationship

The following code shows how to map a one to zero or one relationship (also called an identifying relationship). In the identifying relationship the principal entity (Instructor) is also part of the primary key of the dependent entity (OfficeAssignment).

public class OfficeAssignment
{
    [Key]
    [ForeignKey("Instructor")]
    public Int32 ID { get; set; }

    public string Location { get; set; }
    
    // Navigation property
    public virtual Instructor Instructor { get; set; }
}

public class Instructor
{
    public int InstructorID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public System.DateTime HireDate { get; set; }

    // Navigation properties
    public virtual OfficeAssignment OfficeAssignment { get; set; }
}

Use TimestampAttribute on a Property of Entities That Might Experience a High Degree of Concurrency

We recommend that you define a property with the [Timestamp] attribute on entities that might experience a high degree of concurrency.

public class OfficeAssignment
{
    public Int32 ID { get; set; }
    public string Location { get; set; }

    // When you specify the Timestamp attribute, 
    // the Entity Framework configures ConcurrencyCheck and DatabaseGeneratedPattern=Computed.
    [Timestamp]
    public Byte[] Timestamp { get; set; }
}

Specify Maximum Length on a Required Property

In the following example, the Title property is required and should be no longer than 50 characters. If you do not specify the Title, or if you make it longer than 50 characters, you will get a DbEntityValidationException exception.

public class Course
{
    public int CourseID { get; set; }
    [Required] 
    [MaxLength(50)] 
    public string Title { get; set; }
    public int Credits { get; set; }
}

Use NotMappedAttribute to Exclude a Property from the Database Schema

NotMappedAttribute can be applied to classes or properties. When this attribute is specified, the class or property will not be included in the generated database schema. In the following example, the ExtraInfo property will not be mapped to a column.

public class Department
{
    public int DepartmentID { get; set; }
    public string Name { get; set; }
    [NotMapped]
    public string ExtraInfo {get; set; }
}

Map a Property to a Column with a Different Name

The following code maps the Name property to the DepartmentName column in the database.

public class Department
{
    public int DepartmentID { get; set; }
    [Column("DepartmentName")]
    public string Name { get; set; }
}

Specify That the Class is a Complex Type

The following code defines a complex type Details. It also defines the Details property of the Details type on the OnsiteCourse class. As a result, the OnsiteCourse table will contain the following columns: CourseID, Details_Time, Details_Location, Details_Days.

public class Course
{
    public int CourseID { get; set; }
    public string Title { get; set; }
}

[Table("OnsiteCourse")]
public class OnsiteCourse : Course
{
    public OnsiteCourse()
    {
        Details = new Details();
    }

    public Details Details { get; set; }
}
 
[ComplexType]
public class Details
{
    public System.DateTime Time { get; set; }
    public string Location { get; set; }
    public string Days { get; set; }
}




Build Date:

2012-05-28
Did you find this helpful?
(1500 characters remaining)