In previous article, we have created a class library and created a
UniversityContext. This context had only one model, Student. The POCO class used for this model was very simple, it had few properties.
In previous article, we also have seen that POCO class was used to create the table in database. The datatypes of properties were used to decided data types of columns and the decision was made by EF core.
There are two different ways to apply additional configurations to EF Core models –
- Attributes, which can be placed on the EF Core model properties
- Fluent API, which can use
OnModelCreatingmethod from context
In this article, we are going to see how to use data annotations (i.e. attributes) to refine the EF Core model to specify validations, sizes, data types, etc.
Schema, Table and Column
When a database table is created via EF Core code first approach, default schema is decided by the database server being used. If SQL server is used, default schema is ‘dbo‘.
The table name is name of the DbSet<T> property. Column names are same as property names. SQL Server maps
DateTime properties to
datetime2(7) columns, and
string properties to
nvarchar(max) columns (or to
nvarchar(450) for properties that are used as a key).
Required and Optional
By convention, if null can be assigned to any property, it is by default considered as optional by EF Core.
For example, string can be assigned to null, hence any string property would be treated as optional. While, value types like int or bool cannot be assigned to NULL and hence they are always required properties.
With C# 8, there is a new feature – Nullable Reference Types (NRT) which allows reference types to be annotated, saying whether they can contain NULL or not.
- If NRT is disabled, then all properties with .NET reference types are optional. For example, string would be optional property.
- If NRT is enabled, then it depends on whether the reference types allows NULL or not. For example, string? would be optional property while string would be a required property.
Below code example shows how a .NET reference type can be made required (when NRT is not enabled) – by placing Required attribute on the property.
By convention, if any property has name Id or <Model-Name>Id, then it is by default considered as primary key for that EF Core model. Otherwise, Key attribute can be placed on a property to indicate that it should be a primary key for the model.
In real world applications, primary keys are generally set to autogenerate values. With EF Core, any non-composite integer (for example, int and long) property or a GUID property are by default marked to be auto-generated. There is no need for additional configurations.
On the other hand, if the key has any other data type (non numeric or non GUID), then DatabaseGenerated attribute can be placed to auto-generate the primary key.
By default, string property translates to
nvarchar(max) provided the column is not key for the EF core model. There are two different attributes which allow setting appropriate length on the property.
StringLengthAttribute allows setting min length and/or max length for the column. Alternatively, MaxLength attribute can be used to specify maximum length. Note that minimum length does not affect schema definition. It is just applies minimum length validation rule for the property.
A NotMapped attribute can be placed on a property in an EF core model, indicating that the property does not correspond to any database column and should not create any column in the database.
I hope you find this information useful. Let me know your thoughts.