DatabaseGenerated Attribute in Entity Framework

DatabaseGenerated Attribute in Entity Framework

In this article, I am going to discuss DatabaseGenerated Data Annotation Attribute in Entity Framework Code First Approach with Examples. Please read our previous article where we discussed StringLength Attribute in Entity Framework Code First Approach with Examples.

DatabaseGenerated Attribute in Entity Framework

As we already discussed, by default, Entity Framework API creates an IDENTITY column in the database for the Key Property of the entity (It will not generate an identity column for the composite key or composite primary key). In the case of Primary Key with a single column, SQL Server creates an integer IDENTITY column with identity seed and increment values as 1. So, while inserting a record into the database table, the identity column value will be automatically generated by SQL Server and inserted into the identity column or primary key column.

Entity Framework provides the DatabaseGenerated Data Annotation Attribute which is used to configure how the value of a property will be generated. The DatabaseGenerated Data Annotation Attribute belongs to System.ComponentModel.DataAnnotations.Schema namespace. If you go to the definition of DatabaseGenerated Attribute class, then you will see the following signature. This class specifies how the database generates values for a property.

DatabaseGenerated Attribute in Entity Framework

As you can see in the above image this class has one constructor taking one DatabaseGeneratedOption parameter. Now, if you go to the definition of DatabaseGeneratedOption, then you will see that it is an enum with three values as shown in the below image.

DatabaseGeneratedOption Class in Entity Framework

The DatabaseGenerated Attribute in Entity Framework takes one out of the following three DatabaseGeneratedOption enum values:

  1. DatabaseGeneratedOption.None: If you do not want the database to generate a value then you need to use this option.
  2. DatabaseGeneratedOption.Identity: If you want the database to generate a value for a property when a row is inserted then you need to use this option.
  3. DatabaseGeneratedOption.Computed: If you want the database to generate a value for a property when a row is inserted or updated then you need to use this option.

Let us understand, each of the above options with examples.

DatabaseGeneratedOption.None

The DatabaseGeneratedOption.None option specifies that the value of the property will not be automatically generated by the underlying database. This DatabaseGeneratedOption.None option will be useful to override the default convention for the id properties. If you remember, for the Id Property or <Entity Name>+Id Property, Entity Framework Makes that column Identity Column and will automatically generate the value for that column.

Now, for example, you want to provide your own values to Id Property or <Entity Name>+Id Property instead of autogenerated database values. Then, in this case, we need to use the DatabaseGeneratedOption.None option. For a better understanding, please modify the Student Entity class as follows. As you can see we have decorated the StudentId property with the DatabaseGenerated Attribute with DatabaseGeneratedOption.None value.

using System.ComponentModel.DataAnnotations.Schema;
namespace EFCodeFirstDemo
{
    public class Student
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int StudentId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

In this case, the Entity Framework API will create the StudentId column in the database as the Primary Key Column but will not mark this column as an IDENTITY column. So, we need to specify values for this column explicitly.

As we are going to update the Student Entity Model many times, in order to avoid the Run-Time Exception when the model changes and when we rerun the application, let us set the database initializer as DropCreateDatabaseIfModelChanges. So, modify the context class as follows. As you can see here, we have registered the Student model within the context class using DbSet.

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Setting the Database Initializer as DropCreateDatabaseIfModelChanges
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFCodeFirstContext>());
        }
        
        public DbSet<Student> Students { get; set; }
    }
}

Please make sure to have the connection string with the name MyConnectionString within the app.config file or web.config file as shown in the below image.

DatabaseGenerated Data Annotation Attribute in Entity Framework

Now, modify the Main method of the Program class as follow. Now, as you can see, while creating the Student Entity and before calling the SaveChanges method we need to provide the value for StudentId column. If we omit the StudentId Column, then it will throw an exception. If you are inserting multiple student entities into the database, then for each student entity, the StudentId must be unique. This is because StudentId is the Primary key in the Students table.

using System;
namespace EFCodeFirstDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            using (EFCodeFirstContext context = new EFCodeFirstContext())
            {
                //We need to provide the unique StudentId value
                var student1 = new Student() { StudentId = 101, FirstName = "Pranaya", LastName = "Kumar" };
                context.Students.Add(student1);

                //We need to provide the unique StudentId value
                var student2 = new Student() { StudentId = 102, FirstName = "Hina", LastName = "Sharma" };
                context.Students.Add(student2);

                //The following will throw an exception as StudentId has duplicate value
                //var student3 = new Student() { StudentId = 102, FirstName = "Preety", LastName = "Tiwari" };
                context.SaveChanges();
                Console.WriteLine("Students Added");
                Console.ReadKey();
            }
        }
    }
}
DatabaseGeneratedOption.Identity

It is also possible to mark the non-key properties as DB-Generated properties in Entity Framework by using the DatabaseGeneratedOption.Identity option. This option specifies that the value of the property will be generated automatically by the database on the INSERT SQL statement. This Identity property cannot be updated.

Please note that the way the value of the Identity property will be generated by the database depends on the database provider. It can be identity, rowversion, or GUID. SQL Server makes an identity column for an integer property.

Let us modify the Student Entity as follows. As you can see here, we have applied the DatabaseGeneratedOption.Identity option with DatabaseGenerated Attribute on SequenceNumber property. This will mark the SequenceNumber as the Identity Column in the database. One more point that you need to remember is in a database table, only one column can be marked as Identity. So, in this case, StudentId will be the Primary Key column without Identity and SequenceNumber will be the Identity column.

using System.ComponentModel.DataAnnotations.Schema;
namespace EFCodeFirstDemo
{
    public class Student
    {
        public int StudentId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int SequenceNumber { get; set; }
    }
}

Next, modify the Main Method of the Program class as follows. As you can see, we are providing Unique Values to the StudentId Property and we are not providing any value to the SequenceNumber property whose value is going to be autogenerated by the corresponding database.

using System;
namespace EFCodeFirstDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            using (EFCodeFirstContext context = new EFCodeFirstContext())
            {
                //We need to provide unique StudentId value as StudentId is Primary Key
                //SequenceNumber is auto generated, so need to provide explicit value
                var student1 = new Student() { StudentId = 101, FirstName = "Pranaya", LastName = "Kumar" };
                context.Students.Add(student1);

                //We need to provide the unique StudentId value as StudentId is Primary Key
                //SequenceNumber is auto generated, so need to provide explicit value
                var student2 = new Student() { StudentId = 102, FirstName = "Hina", LastName = "Sharma" };
                context.Students.Add(student2);
                
                context.SaveChanges();
                Console.WriteLine("Students Added");
                Console.ReadKey();
            }
        }
    }
}

Note: The DatabaseGeneratedOption.Compute option not supported with Data Annotation Attribute with Entity Framework Code First Approach. We will discuss this when we will discuss Fluent API and Entity Framework Core.

In the next article, I am going to discuss TimeStamp Attribute in Entity Framework Code First Approach with Examples. Here, in this article, I try to explain DatabaseGenerated Data Annotation Attribute in Entity Framework Code First Approach with Examples. I hope you enjoyed this DatabaseGenerated Attribute in Entity Framework Code First Approach with Examples article. Please give your valuable feedback and suggestions about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *