问题描述
上下文是每个 Car
有一个对应的 CarBrand
。现在我的班级如下所示:
The context is each Car
has a corresponding CarBrand
. Now my classes are as shown below:
public class Car
{
public int CarId { get; set; }
public int CarBrandId { get; set; }
public CarBrand CarBrand { get; set; }
}
public class CarBrand
{
public int CarBrandId { get; set; }
public string Name { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<CarBrand> CarBrands { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(@"Data Source = MyDatabase.sqlite");
}
}
这是我的代码的示例执行... / p>
Here's a sample execution of my code...
class Program
{
static void Main(string[] args)
{
AlwaysCreateNewDatabase();
//1st transaction
using (var context = new MyContext())
{
var honda = new CarBrand() { Name = "Honda" };
var car1 = new Car() { CarBrand = honda };
context.Cars.Add(car1);
context.SaveChanges();
}
//2nd transaction
using (var context = new MyContext())
{
var honda = GetCarBrand(1);
var car2 = new Car() { CarBrand = honda };
context.Cars.Add(car2);
context.SaveChanges(); // exception happens here...
}
}
static void AlwaysCreateNewDatabase()
{
using (var context = new MyContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
}
}
static CarBrand GetCarBrand(int Id)
{
using (var context = new MyContext())
{
return context.CarBrands.Find(Id);
}
}
}
问题是我得到唯一约束失败:将 car2
与相同的 CarBrand $添加到数据库时,CarBrands.CarBrandId
异常c $ c> 本田
。
The problem is I get 'UNIQUE constraint failed: CarBrands.CarBrandId' exception when car2
is being added to the database with the same CarBrand
honda
.
我希望它在第二次交易期间执行context.SaveChanges()
,它将添加 car2
并设置其与 CarBrand
的关系
What I expect it to do is during 2nd transaction's context.SaveChanges()
, it will add car2
and set it's relationship with CarBrand
appropriately but I get an exception instead.
编辑:我真的需要在不同的上下文/事务中获取我的CarBrand实例。
I really need to get my CarBrand instance in a different context/transaction.
//really need to get CarBrand instance from different context/transaction
CarBrand hondaDb = null;
using (var context = new MyContext())
{
hondaDb = context.CarBrands.First(x => x.Name == "Honda");
}
//2nd transaction
using (var context = new MyContext())
{
var car2 = new Car() { CarBrand = hondaDb };
context.Cars.Add(car2);
context.SaveChanges(); // exception happens here...
}
推荐答案
问题是方法级联:
The problem is that Add
method cascades:
有很多方法可以实现目标,但是最灵活(我想首选)是将 Add
方法调用替换为方法:
There are many ways to achieve the goal, but the most flexible (and I guess the preferred) is to replace the Add
method call with the ChangeTracker.TrackGraph
method:
因此,代替 context.Cars.Add(car2);
使用以下命令(它很通用,应该在几乎所有情况下都可以使用):
So instead of context.Cars.Add(car2);
you could use the following (it's pretty generic and should work in almost all scenarios):
context.ChangeTracker.TrackGraph(car2, node =>
node.Entry.State = !node.Entry.IsKeySet ? EntityState.Added : EntityState.Unchanged);
这篇关于EF核心/ Sqlite一对多关系由于唯一索引约束而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!