-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue with "Id" property when using upsert with SqlServer dbcontext #125
Comments
I'm having the same issue and I believe it's because FlexLabs.Upsert library excludes properties where
@theeheng , as the comment suggests, one work around is enforce Id generation on the server: modelBuilder
.Entity<UserProgramRoleEntity>()
.Property(role => role.Id)
.HasDefaultValueSql("newsequentialid()"); @artiomchi do you think there's a way to detect if the value will be generated client-side or server side and generate the MERGE statement accordingly for SQL server? var allowInserts = p.ValueGenerated == ValueGenerated.Never
|| p.IsGuid()
|| p.GetAfterSaveBehavior() == PropertySaveBehavior.Save; |
I've also just hit this issue, using a GUID ID. |
Not 100% sure, but I think EF core assumes the Id property is database generated. I have added the
Also, not sure if this is different for MsSQL since I am using PostgreSQL. The entity
Hope it helps. |
Here is my entity class:
public class UserProgramRoleEntity
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public Guid ProgramId { get; set; }
public ProgramRole ProgramRole { get; set;}
public bool Deleted { get; set; }
}
and I try to call upsert with the following statement:
var userProgramRoleEntities = new List {
new UserProgramRoleEntity {
Id = Guid.NewGuid(),
UserId = 1,
ProgramId = 2,
ProgramRole = "test",
Deleted = false
},
new UserProgramRoleEntity {
Id = Guid.NewGuid(),
UserId = 1,
ProgramId = 2,
ProgramRole = "test2",
Deleted = false
}
};
await context.UserProgramRoleEntity.UpsertRange(userProgramRoleEntities)
.On(c => new { c.UserId, c.ProgramId, c.ProgramRole })
.WhenMatched(x => new ReportingUserProgramRoleEntity { Deleted = true } )
.RunAsync();
It throws an error to say that :
Microsoft.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'Id', table 'dbo.UserProgramRoleEntities'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
Here is the sql its generated :
MERGE INTO [UserProgramRoleEntities] WITH (HOLDLOCK) AS [T]
USING ( VALUES (@p0, @p1, @p2, @p3) ) AS [S] ([Deleted], [ProgramId], [ProgramRole], [UserId])
ON [T].[UserId] = [S].[UserId] AND [T].[ProgramId] = [S].[ProgramId] AND [T].[ProgramRole] = [S].[ProgramRole]
WHEN NOT MATCHED BY TARGET THEN INSERT ([Deleted], [ProgramId], [ProgramRole], [UserId])
VALUES ([Deleted], [ProgramId], [ProgramRole], [UserId]) WHEN MATCHED THEN UPDATE SET [Deleted] = [S].[Deleted];
Any idea why its missing the 'Id' property in the insert statement since 'Id' property is not an auto generated column? My unit test is running fine when I have the dbContextOption calling build.UseInMemoryDatabase but failed when using builder.UseSqlServer. So it seems something wrong with the SqlServer driver
The text was updated successfully, but these errors were encountered: