C
C#3w ago
Zoli

✅ UNIQUE constraint failed

I have the following relationships One workout can have multiple exercises and each exercise can have one exercise variant I would like to implement this but I am getting an exception when saving a newly created workout
An error occurred while saving the entity changes.See the inner exception for details. // ---> Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 19: 'UNIQUE constraint failed: ExerciseVariant.Id'.
My classes
[Table(nameof(Workout))]
public class Workout
{
[Key]
public Guid Id { get; set; }

// Other properties

public ICollection<Exercise> Exercises { get; } = new List<Exercise>();
}


[Table(nameof(Exercise))]
public class Exercise
{
[Key]
public Guid Id { get; set; }

// Relationship with ExerciseVariant
public Guid ExerciseVariantId { get; set; } // Foreign key
public ExerciseVariant ExerciseVariant { get; set; } = null!; // Navigation property

// Relationship with Workout
public Guid? WorkoutId { get; set; }
public Workout? Workout { get; set; }

// Other properties
}

[Table(nameof(ExerciseVariant))]
public class ExerciseVariant
{
[Key]
public Guid Id { get; set; }

public ICollection<Exercise> Exercises { get; } = new List<Exercise>();

// Other properties
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure relationships
modelBuilder.Entity<Exercise>()
.HasOne(e => e.ExerciseVariant)
.WithMany(ev => ev.Exercises)
.HasForeignKey(e => e.ExerciseVariantId);

// Workouts
modelBuilder.Entity<Workout>()
.HasMany(o => o.Exercises)
.WithOne(o => o.Workout)
.HasForeignKey(o => o.WorkoutId)
.OnDelete(DeleteBehavior.Cascade);

base.OnModelCreating(modelBuilder);
}
[Table(nameof(Workout))]
public class Workout
{
[Key]
public Guid Id { get; set; }

// Other properties

public ICollection<Exercise> Exercises { get; } = new List<Exercise>();
}


[Table(nameof(Exercise))]
public class Exercise
{
[Key]
public Guid Id { get; set; }

// Relationship with ExerciseVariant
public Guid ExerciseVariantId { get; set; } // Foreign key
public ExerciseVariant ExerciseVariant { get; set; } = null!; // Navigation property

// Relationship with Workout
public Guid? WorkoutId { get; set; }
public Workout? Workout { get; set; }

// Other properties
}

[Table(nameof(ExerciseVariant))]
public class ExerciseVariant
{
[Key]
public Guid Id { get; set; }

public ICollection<Exercise> Exercises { get; } = new List<Exercise>();

// Other properties
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure relationships
modelBuilder.Entity<Exercise>()
.HasOne(e => e.ExerciseVariant)
.WithMany(ev => ev.Exercises)
.HasForeignKey(e => e.ExerciseVariantId);

// Workouts
modelBuilder.Entity<Workout>()
.HasMany(o => o.Exercises)
.WithOne(o => o.Workout)
.HasForeignKey(o => o.WorkoutId)
.OnDelete(DeleteBehavior.Cascade);

base.OnModelCreating(modelBuilder);
}
ExerciseVariants is bulked inserted from an api when the app first launched.
15 Replies
Zoli
ZoliOP3w ago
When I want to create a workout:
var first = await _dbContext.ExerciseVariant.FirstOrDefaultAsync();
var workout = new Workout()
{
Title = "test",
};
var exercise = new Exercise()
{
ExerciseVariant = first,
ExerciseVariantId = first.Id
};

workout.Exercises.Add(exercise);

await _dbContext.Workout.AddAsync(workout).ConfigureAwait(false);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
var first = await _dbContext.ExerciseVariant.FirstOrDefaultAsync();
var workout = new Workout()
{
Title = "test",
};
var exercise = new Exercise()
{
ExerciseVariant = first,
ExerciseVariantId = first.Id
};

workout.Exercises.Add(exercise);

await _dbContext.Workout.AddAsync(workout).ConfigureAwait(false);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
I am getting an exception as
An error occurred while saving the entity changes.See the inner exception for details. // ---> Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 19: 'UNIQUE constraint failed: ExerciseVariant.Id'.
What am I doing worng? Since ExerciseVariant is read only kind of metadata do I need to add ? public ICollection<Exercise> Exercises { get; } = new List<Exercise>();
Sehra
Sehra3w ago
try removing ExerciseVariantId = first.Id, you already connect them on the line above
Zoli
ZoliOP3w ago
Still the same.
Sehra
Sehra3w ago
check what await _dbContext.ExerciseVariant.FirstOrDefaultAsync() returns, i got same error if it was null after putting something in the table, the example worked fine
Zoli
ZoliOP3w ago
I am getting a valid ExerciseVariant.
No description
Sehra
Sehra3w ago
are you reusing the same DbContext?
Zoli
ZoliOP3w ago
I think yes I do. I have a UoW wrapper around dbcontext
No description
Sehra
Sehra3w ago
the context is already a unit of work
Zoli
ZoliOP3w ago
Yes I know just wanted to extend with some custom methods and etc. Is using the same DbContext should be avoided?
Sehra
Sehra3w ago
yes, it should be short lived you can use .AddDbContextFactory and inject that to construct context instances
Zoli
ZoliOP3w ago
So in this case i register only UnitOfWork in the Di so means all repository gets the same DbContext. How is it possible to inject new for each repository?
Sehra
Sehra3w ago
don't forget to dispose of them. or use service scopes
Sehra
Sehra3w ago
Implementing the infrastructure persistence layer with Entity Frame...
.NET Microservices Architecture for Containerized .NET Applications | Explore the implementation details for the infrastructure persistence layer, using Entity Framework Core.
Zoli
ZoliOP3w ago
Ohhh looks good thanks a lot 🍻 Probably it will solve my issue. One more question if you dont mind. I have the ExerciseVariant table which is kind of metadata so only read only.
[Table(nameof(ExerciseVariant))]
public class ExerciseVariant
{
[Key]
public Guid Id { get; set; }

public ICollection<Exercise> Exercises { get; } = new List<Exercise>();

// Other properties
}
[Table(nameof(ExerciseVariant))]
public class ExerciseVariant
{
[Key]
public Guid Id { get; set; }

public ICollection<Exercise> Exercises { get; } = new List<Exercise>();

// Other properties
}
Do I need this list of exercise at all? Each exercise can have one exercise variant, and exercise variant can be used for multiple exercise
Sehra
Sehra3w ago
they are all optional and for convenience. you can always tell ef core about entity relationships in OnModelCreating instead sometimes you want to find all related entities and then a collection is useful instead of creating the query yourself if the model changes to for example using a composite primary key, a navigation property would continue to generate the correct query, while a manual query would need to be updated

Did you find this page helpful?