When using the InterBaseSql.EntityFrameworkCore.InterBase Version 10.0.2 we are unable to delete an entity.
Removing an entity and calling context.SaveChanges() always throws an Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException.
See unit test InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd.Delete() as code snippet to reproduce. This test fails.
|
public void Delete() |
|
{ |
|
using (var db = GetDbContext<DeleteContext>()) |
|
{ |
|
db.Database.ExecuteSqlRaw("create table test_delete (id int not null, name varchar(20), primary key (ID))"); |
|
db.Database.ExecuteSqlRaw("insert into test_delete values (65, 'test')"); |
|
db.Database.ExecuteSqlRaw("insert into test_delete values (66, 'test')"); |
|
db.Database.ExecuteSqlRaw("insert into test_delete values (67, 'test')"); |
|
var entity = new DeleteEntity() { Id = 66 }; |
|
var entry = db.Attach(entity); |
|
entry.State = EntityState.Deleted; |
|
db.SaveChanges(); |
Calling SaveChanges() throws the exception within Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch::Consume(RelationalDataReader reader).
https://github.com/dotnet/efcore/blob/6119066c37b98f604a5c868d691da0405d53e1aa/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs#L121C33-L121C74
The reader inside has no rows, only the property reader.RecordsAffected == 1.
See ResultSetMapping == ResultSetMapping.LastInResultSet where EF tries to get a row which does not exist.
https://github.com/dotnet/efcore/blob/6119066c37b98f604a5c868d691da0405d53e1aa/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs#L62C1-L66C1
IBUpdateSqlGenerator.AppendDeleteOperation() sets the ResultSetMapping to ResultSetMapping.LastInResultSet.
|
public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) |
|
{ |
|
var name = command.TableName; |
|
var operations = command.ColumnModifications; |
|
var conditionOperations = operations.Where(o => o.IsCondition).ToList(); |
|
var inputOperations = GenerateParameters(conditionOperations); |
|
AppendDeleteCommandHeader(commandStringBuilder, name, null); |
|
AppendWhereClause(commandStringBuilder, conditionOperations); |
|
commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); |
|
requiresTransaction = true; |
|
return ResultSetMapping.LastInResultSet; |
|
} |
The InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal::AppendUpdateOperation sets the ResultSetMapping to ResultSetMapping.NoResults.
|
public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) |
|
{ |
|
var name = command.TableName; |
|
var operations = command.ColumnModifications; |
|
var writeOperations = operations.Where(o => o.IsWrite).ToList(); |
|
var readOperations = operations.Where(o => o.IsRead).ToList(); |
|
var conditionOperations = operations.Where(o => o.IsCondition).ToList(); |
|
var anyRead = readOperations.Any(); |
|
AppendUpdateCommandHeader(commandStringBuilder, name, null, writeOperations); |
|
AppendWhereClause(commandStringBuilder, conditionOperations); |
|
commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); |
|
|
|
//if (anyRead) |
|
//{ |
|
// var keyOperations = operations.Where(o => o.IsKey).ToList(); |
|
|
|
// return AppendSelectAffectedCommand(commandStringBuilder, name, null, readOperations, keyOperations, commandPosition); |
|
//} |
|
// commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); |
|
requiresTransaction = true; |
|
return ResultSetMapping.NoResults; |
|
} |
Just to doublecheck, I modified AppendDeleteOperation to return ResultSetMapping.NoResults.
=> UnitTest Delete() passes.
Doing the same im my project and Remove/Delete works as expected.
Problem: Changing this behaviour means there is no UpdateConcurrency check any more (which would be appreciated for AppendUpdateOperation as well).
UnitTest InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd::ConcurrencyDelete => fail
UnitTest InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd::Delete => pass
Could you please help us with this issue? Delete functionality is essential.
Thanks and with kind regards,
When using the InterBaseSql.EntityFrameworkCore.InterBase Version 10.0.2 we are unable to delete an entity.
Removing an entity and calling
context.SaveChanges()always throws anMicrosoft.EntityFrameworkCore.DbUpdateConcurrencyException.See unit test
InterBaseSql.EntityFrameworkCore.InterBase.Tests.EndToEnd.Delete()as code snippet to reproduce. This test fails.IB.NETDataProvider/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase.Tests/EndToEnd/DeleteTests.cs
Lines 53 to 64 in 0015a71
Calling
SaveChanges()throws the exception withinMicrosoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch::Consume(RelationalDataReader reader).https://github.com/dotnet/efcore/blob/6119066c37b98f604a5c868d691da0405d53e1aa/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs#L121C33-L121C74
The
readerinside has no rows, only the propertyreader.RecordsAffected == 1.See
ResultSetMapping == ResultSetMapping.LastInResultSetwhere EF tries to get a row which does not exist.https://github.com/dotnet/efcore/blob/6119066c37b98f604a5c868d691da0405d53e1aa/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs#L62C1-L66C1
IBUpdateSqlGenerator.AppendDeleteOperation()sets theResultSetMappingtoResultSetMapping.LastInResultSet.IB.NETDataProvider/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBUpdateSqlGenerator.cs
Lines 87 to 98 in 0015a71
The
InterBaseSql.EntityFrameworkCore.InterBase.Update.Internal::AppendUpdateOperationsets theResultSetMappingtoResultSetMapping.NoResults.IB.NETDataProvider/NETProvider/Provider/src/InterBaseSql.EntityFrameworkCore.InterBase/Update/Internal/IBUpdateSqlGenerator.cs
Lines 64 to 85 in 0015a71
Just to doublecheck, I modified
AppendDeleteOperationto returnResultSetMapping.NoResults.=> UnitTest
Delete()passes.Doing the same im my project and Remove/Delete works as expected.
Problem: Changing this behaviour means there is no UpdateConcurrency check any more (which would be appreciated for AppendUpdateOperation as well).
Could you please help us with this issue? Delete functionality is essential.
Thanks and with kind regards,