【问题标题】:EF6 with Sqlite one-to-many relationship failing on Unique Constraint具有 Sqlite 一对多关系的 EF6 在唯一约束上失败
【发布时间】:2020-07-27 08:44:56
【问题描述】:

我在使用 Entity Framework 6 将具有一对多关系的实体插入 SQLite 数据库时遇到了问题。让我们考虑这个示例:

型号

public class Box {
    public int BoxId { get; set; }
    public ICollection<Item> Items{ get; set; }
}

public class Item {
    public int ItemId { get; set; }
    public Box Box { get; set; }
}

插入

Box box = new Box(){BoxId = 1};
Item item = new Item(){ItemId = 1, Box = box};
using (var db = new MyDbContext()) {
    db.Boxes.Add(box);
    db.SaveChanges();
    db.Items.Add(item);
    db.SaveChanges();
}

这个 sn-p 有效。

Box box = new Box(){BoxId = 1};
Item item = new Item(){ItemId = 1, Box = box};
using (var db = new MyDbContext()) {
    db.Boxes.Add(box);
    db.SaveChanges();
}
using (var db = new MyDbContext()) {
    db.Items.Add(item);
    db.SaveChanges();
}

这个 sn-p 不起作用,抛出一个异常,消息 UNIQUE constraint failed

我明白为什么它不起作用,但我想不出办法让它起作用。使用相同的上下文不是一个选项,因为应用程序可能会在创建 Box 和添加 Item 之间重新启动。我找到了相同问题的答案,但使用的是 EF 核心而不是 EF6 (right there (Stack Overflow)),但我无法使用 EF6 访问 ChangeTrackerTrackGraph 属性。

我还需要一个完全通用的方法来解决这个问题,因为我的 Boxes 中可能有其他对象而不是 Items。

【问题讨论】:

  • 只用 try-catch 换行。
  • @AlexanderPetrov 然后呢?我需要通用的解决方案,我不能在捕获中处理特殊情况。
  • 如果抛出异常则什么也不做。项目已在之前的 using 块中添加。
  • 不,不是,只是在第一个 using 块中添加了框。我可能在第一个 using 块之后初始化了 item,结果是一样的。
  • 项目是通过导航属性添加的。这就是您得到异常的原因。

标签: c# sqlite entity-framework-6


【解决方案1】:

好吧,我想办法了。

在调用db.SaveChanges() 之前,我执行了这段代码,其中entities 是我刚刚添加到DbContext 中的实体列表。这样只添加我明确想要添加的实体,不添加其他相关实体,因此我不会遇到唯一约束失败,因为 DbContext 没有重新创建相关实体。

db.ChangeTracker.Entries().ToList().ForEach(dbe => {
    if (!entities.Contains(dbe.Entity)) {
        dbe.State = EntityState.Unchanged;
    }
});

【讨论】:

    猜你喜欢
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 2016-05-01
    • 2018-06-29
    • 2010-12-15
    • 2015-05-22
    • 1970-01-01
    相关资源
    最近更新 更多