Mauricio Pastorini
Mauricio Pastorini

Reputation: 842

Can't update entity with unique constraint index in Entity Framework

I have an entity Invoice with 1 Provider and many ParticularFieldValues. In my invoice I have a unique index constraint in attribute InvoiceNumber.

The problem is that I want to do minimal changes in Invoice, it throw an exception saying that I can't SaveChanges because of duplicated unique index InvoiceNumber.

I also tried with attach and it said that I cant because of the same duplicated.

Here is my table diagram:

enter image description here

enter image description here

Invoice class:

public class Invoice
{
        public int InvoiceId { get; set; }
        public int InvoiceNumber { get; set; }
        public virtual int ProviderId { get; set; }
        public virtual Provider Provider { get; set; }

        public virtual ICollection<ParticularFieldValue> ParticularProviderFieldsToComplete { get; set; }

        public DateTime DueDate { get; set; }

        public int TotalAmount { get; set; }
}

Here is the operation I can't do:

public void UpdatePayment(Invoice inv)
{
            UnitOfWork.Invoices.Update(inv);
            UnitOfWork.Save();
}

public void Update(Invoice inv)
{
            Invoice invDb = base.Get(inv.InvoiceId);
            invDb.TotalAmount = inv.TotalAmount;
}

public TEntity Get(int id)
{
            return dbSet.Find(id);
}

And the exception:

"ExceptionMessage": "An error occurred while updating the entries. See the inner exception for details.",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "No se puede insertar una fila de clave duplicada en el objeto 'dbo.Invoices' con índice único 'IX_InvoiceNumber'. El valor de la clave duplicada es (123451).\r\nSe terminó la instrucción.",
"ExceptionType": "System.Data.SqlClient.SqlException",
"StackTrace": "
en System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction)
en System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction)
en System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
en System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
en System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
en System.Data.SqlClient.SqlDataReader.get_MetaData()
en System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption)
en System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) en System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
en System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
en System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
en System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
en System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
en System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext
1 c) en System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func3 operation, TInterceptionContext interceptionContext, Action3 executing, Action3 executed)\r\n en System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)\r\n en System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n en System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)\r\n en System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.Execute(Dictionary2 identifierValues, List1 generatedValues)\r\n en System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update()

Upvotes: 1

Views: 1352

Answers (1)

Taras
Taras

Reputation: 1

Had the same issue, it turned out that before updating the entity, I first tried to add it, and if the record was already there, then under certain conditions I changed this record. And at the time of adding, when the error popped up that the record already exists, I forgot to call the Detach on this entity in time, so when I later tried to update my property, the first thing DbContext tried to do was add an entity that already exists in db (because of this, the error about the unique index was caused), but it never got to the point of updating. In short, check whether you have summoned Detach from entities everywhere.

Upvotes: 0

Related Questions