本文介绍了EF核心/ Sqlite一对多关系由于唯一索引约束而失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文是每个 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 异常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一对多关系由于唯一索引约束而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 03:35