-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
SQLite Error 19: 'UNIQUE constraint failed' when using same DbConnection different DbContext instances #15819
Comments
@tico321 Given that the code above creates two Note for triage: full repro code below. Somehow EF ends up using the tracked entity instance instead of the new entity instance. public class EntityB
{
public int EntityBId { get; set; }
public EntityA EntityA { get; set; }
}
public class EntityA
{
public int EntityAId { get; set; }
public int? EntityBId { get; set; }
public EntityB EntityB { get; set; }
}
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions options) : base(options)
{
}
public DbSet<EntityA> AEntities { get; set; }
public DbSet<EntityB> BEntities { get; set; }
}
public class Program
{
public static void Main()
{
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
try
{
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseSqlite(connection)
.Options;
using (var context = new BloggingContext(options))
{
context.Database.EnsureCreated();
context.BEntities.Add(new EntityB { EntityBId = 1 });
context.SaveChanges();
}
using (var context = new BloggingContext(options))
{
var b1 = context.BEntities.ToList().Single();
var b2 = new EntityB { EntityBId = 1 };
context.Add(new EntityA { EntityAId = 1, EntityB = b2 });
context.SaveChanges();
var bs = context.BEntities.Local.ToList(); // Only one b, and it's b1!
}
}
finally
{
connection.Close();
}
}
} |
@ajcvickers Thank you for your response. You made me realize it was my mistake. Basically I was expecting this to work: using (var context = new BloggingContext(options))
{
var b2 = new EntityB { EntityBId = 1 };
context.Add(new EntityA { EntityAId = 1, EntityB = b2 });
context.SaveChanges();
var bs = context.BEntities.Local.ToList(); // Only one b, and it's b1!
} As equivalent to this: using (var context = new BloggingContext(options))
{
var b2 = new EntityB { EntityBId = 1 };
// I realized it's needed to attach it so EF won't try to create a new one
context.Bentities.Attach(b2);
context.Add(new EntityA { EntityAId = 1, EntityB = b2 });
context.SaveChanges();
} And after your example we can see that we can accomplish the same result by loading the entity, and EF will use the tracked one.... Thanks again you for your time and help! |
Sqlite throws Microsoft.Data.Sqlite.SqliteException : SQLite Error 19: 'UNIQUE constraint failed:
when you use the same connection in different instances of DbContext and you have a relationship of 0 to 1.
Here is a sample project with 3 unit tests where the problem can be reproduced:
https://github.com/tico321/SQLiteUniqueErrorSeparateUsings/blob/master/SQLiteUniqueError/UnitTest1.cs
Also note that the problem only happens when there are already stored entities in this case BEntities.
We can see that if we run the test using the same DbContext it will pass:
Also weird but a workaround is that if we load the BEntities in the second using the test will pass:
The issue is that the test will fail without the workaround where we list BEntities and will throw the Unique Constraint failed error.
Further technical details
EF Core version: 2.2.
Microsoft.EntityFrameworkCore.Sqlite: 2.2.4
Operating system: Windows 10
IDE: Visual Studio 2019
The text was updated successfully, but these errors were encountered: