Entity Framework batch update violating an IsUnique constraint

entity-framework entity-framework-core

Question

Here's a couple of entities in our database

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

    public IList<QuestionEvent> Questions { get; set; }
}

public class QuestionEvent
{
    public Event Event { get; set; }

    public int EventId { get; set; }

    public int Order { get; set; }
}

And here's how the relationship is defined in the context.

builder.Entity<QuestionEvent>().HasIndex(x => new
{
    x.EventId,
    x.Order
}).IsUnique();
builder.Entity<QuestionEvent>().HasOne(x => x.Event).WithMany(x => x.Questions).HasForeignKey(x => x.EventId);
builder.Entity<QuestionEvent>().HasOne(x => x.Question).WithMany(x => x.QuestionEvents).HasForeignKey(x => x.QuestionId);

If you try to an Event with multiple QuestionEvents in which the values of Order have changed, the system throws a circular dependency error.

2018-09-20 10:32:35.252 +01:00 [ERR] Unable to save changes because a circular dependency was detected in the data to be saved:
'QuestionEvent [Modified]
<- Index { 'EventId', 'Order' } QuestionEvent [Modified]
<- Index { 'EventId', 'Order' } QuestionEvent [Modified]
<- Index { 'EventId', 'Order' } QuestionEvent [Modified]'.

Here's the

At a guess what's happening here is that EF is unable to update "order" because of that unique constraint - if the order has changed, then during the update process, there will be a point where it's likely two entities will have the same value.

What I can't see is whether there's any way out of this problem without moving that constraint. However I dice it up in my head, we're left with the same issue, whether you try to do the updates as individual transactions, a batch, or wrap the thing in a transaction (which I've tried).

Is there a way round this?

1
0
9/20/2018 10:02:40 AM

Popular Answer

You could save a dummy value in one entity, update the other entity, then set the correct value in the first entity. This can be abstracted by writing a method utilizing the entities' EntityEntry to check if the modified index properties' current value equals one of the other entities' modified index properties' original values.

0
9/21/2018 7:20:25 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow