This is Entity Framework 6.1.3
The SQL Server table has a two-column composite key.
ID INT Identity(1,1) NOT NULL
VERSION INT NOT NULL
Inserting a new record works because I don't set the ID on my object; I only set the VERSION. So a new record would look like this:
ID VERSION
1 1
Perfect! The database generates the ID because the column is configured with Identity and my model is decorated with [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
But now I need to insert another row with the same ID but a different VERSION; hence the composite key. So I would expect the second row to be:
ID Version
1 1
1 2 <- second row has same ID and different version
I do need this to work both ways because there is the scenario where a new ID should be auto-generated by the database, and the other scenario where I have the same ID but a different VERSION.
The Problem: Because my Code-First model has the ID configured with DatabaseGeneratedOption.Identity, when I set the ID property on my object, my SaveChanges generates the insert statement without the ID!
(Diagnostic Tools in VS shows that Entity Framework generated this statement)
ADO.NET: Execute Reader "INSERT [dbo].[T1]([Version], ... VALUES (@0, ...)
Note the omission of ID. Because I explicitly set the ID on my object, I expected to see this statement instead.
INSERT [dbo].[T1]([ID], [Version], ... VALUES (@0, @1, ...)
That's what I'm trying to accomplish.
The question is: How can I make Entity Framework include that ID column in its generated insert statement in an elegant way?
I don't want to use a stored procedure or hard code a SQL statement or hack the insert statement by 'squeezing in' the column.
If there is no way, I know that I would have to remove the use of Identity altogether and define my own IDs, which I'm trying to avoid.
Also, my SaveChanges() already makes use of SET IDENTITY_INSERT ON/OFF so that isn't any problem.
Here is the relevant part of my model: (I omitted other properties)
[Key, Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Key, Column(Order = 1)]
public int VERSION { get; set; }
One avenue that I've explored was to reset my DbContext with a twist in OnModelCreating, but that didn't make a difference. Of course, in that revision I did remove the DatabaseGenerated decorator off my ID property in the class. I inserted this into OnModelCreating:
if (this.AllowIdentityInsert)
{
modelBuilder.Entity<T1>().Property(x => x.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
else
{
modelBuilder.Entity<T1>().Property(x => x.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
If I could successfully control the model by changing the ID property to DatabaseGeneratedOption to None before my SaveChanges, then this could work and be an elegant solution.
Has anyone run into this situation and found a good solution? Thanks so much for your input or suggestions.