Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a property to be "Identity" or auto-incremented column with Entity Framework Core?

In a new WPF project that I am writing using c#, I want to attempt on using Entity Framework Core to interact with my SQL Server database.

Every time I try to add model to my context, I get the following error

Cannot insert explicit value for identity column in table 'Orders' when IDENTITY_INSERT is set to OFF.

I am using a Repository and UnitOfWork which wraps the Entity Framework Core methods to perform the work needed.

But at its simplest, I am executing the following code

var order = new Order();
order.Title = "some";
....
Context.Orders.Add(order);
Context.SaveChanges();

Here is my model

public class Order
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Int64 Id { get; set; }

    public string Status { get; set; }
    public int? CustomerId { get; set; }
    public DateTime? Birthdate { get; set; }
    public int UtcOffset { get; set; }\
    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
    public int? UpdatedBy { get; set; }

    [ForeignKey(nameof(Creator))]
    public int CreatedBy { get; set; }

    public Order()
    {
        CreatedAt = DateTime.UtcNow;
    }

    public virtual User Creator { get; set; }
    public virtual Customer Customer { get; set; }
}

What could be causing this problem?

Updated

Here is how my table is created

CREATE TABLE [dbo].[Orders](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Status] [varchar](50) NOT NULL,
    [CustomerId] [int] NULL,
    [Birthdate] [datetime] NULL,
    [CreatedBy] [int] NOT NULL,
    [CreatedAt] [datetime] NOT NULL,
    [UpdatedBy] [int] NULL,
    [UpdatedAt] [datetime] NULL,
    [UtcOffset] [int] NOT NULL,
 CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Here is the method that creates the Order model

public Order Create(int? customerId, DateTime? birthdate)
{
    var order = new Order();
    order.CustomerId = customerId;
    order.Birthdate = birthdate;
    order.Status = OrderStatus.Sold.ToString();
    order.CreatedBy = Passport.Identity.Id;

    var updatedOrder = Orders.Add(order);
    Orders.Save();

    return updatedOrder;
}

Here is my repository implementation

public class EntityRepository<TEntity, TKeyType> : IRepository<TEntity, TKeyType>
    where TEntity : class
    where TKeyType : struct
{
    protected readonly DbContext Context;
    protected readonly DbSet<TEntity> DbSet;

    public EntityRepository(DbContext context)
    {
        Context = context;
        DbSet = context.Set<TEntity>();
    }

    public TEntity Get(TKeyType id)
    {
        return DbSet.Find(id);
    }

    public IEnumerable<TEntity> GetAll()
    {
        return DbSet.ToList();
    }

    public bool Any(Expression<Func<TEntity, bool>> predicate)
    {
        return DbSet.Any(predicate);
    }

    public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate)
    {
        return DbSet.SingleOrDefault(predicate);
    }

    public virtual TEntity Add(TEntity entity)
    {
        DbSet.Add(entity);

        return entity;
    }

    public virtual IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities)
    {
        DbSet.AddRange(entities);

        return entities;
    }

    public void Remove(TEntity entity)
    {
        DbSet.Remove(entity);
    }

    public void RemoveRange(IEnumerable<TEntity> entities)
    {
        DbSet.RemoveRange(entities);
    }

    public void Update(TEntity entity)
    {
        DbSet.Attach(entity);
        var record = Context.Entry(entity);
        record.State = EntityState.Modified;
    }

    public IQueryable<TEntity> Query()
    {
        return DbSet;
    }

    public void Save()
    {
        Context.SaveChanges();
    }
}

public class EntityRepository<TEntity> : EntityRepository<TEntity, int>
   where TEntity : class
{
    public EntityRepository(DbContext context)
        : base(context)
    {
    }
}

Additionally, this question is not a duplicate on Entity Framework error: Cannot insert explicit value for identity column in table because I am decorating my Id property with the [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]. Moreover, I am using database first approach, so I created my database manually using MSSMS

like image 727
Junior Avatar asked May 21 '18 00:05

Junior


People also ask

How do you set an explicit value to ID property in EF core?

ExecuteSqlCommand() method and set IDENTITY_INSERT ON. Then we called the SaveChanges() method. This will insert a new Student record where StudentId will be 100 in the database. Thus, you can set an explicit value to the id property manually.

How can we specify computed generated column in Entity Framework?

The Entity Framework Core Fluent API HasComputedColumnSql method is used to specify that the property should map to a computed column. The method takes a string indicating the expression used to generate the default value for a database column.

What is Databasegenerated DatabaseGeneratedOption identity?

DatabaseGeneratedOption.IdentityThis specifies that the value of the property will be generated by the database on the INSERT 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.

What is ValueGeneratedOnAdd?

The Entity Framework Core Fluent API ValueGeneratedOnAdd method indicates that the value for the selected property is generated by the database whenever a new entity is added to the database. Therefore, the property should be ignored by EF Core when constructing an INSERT statement.


1 Answers

In my case I had to add entity.Property(e => e.TranId).ValueGeneratedOnAdd(); to my context file.

modelBuilder.Entity<PersonalTrades>(entity =>
{
     entity.Property(e => e.TranId).ValueGeneratedOnAdd();
}

I was not updating the identity field(TranId) from Automapper. Finally the above change worked for me which, as the name specifies, generates the value for the identity field while inserting the record.

like image 158
Sachin Parashar Avatar answered Sep 23 '22 15:09

Sachin Parashar