【问题标题】:Fix 'The DELETE statement conflicted with the REFERENCE constraint' error with code使用代码修复“DELETE 语句与 REFERENCE 约束冲突”错误
【发布时间】:2014-02-03 08:47:19
【问题描述】:

我有一个带有 EntityFramework Code First 的 Asp.Net MVC 5 网站。在我的站点中,我有一个 Restaurant 模型,其代码如下:

public class Restaurant
{
    [Required]
    public string Name { get; set; }

    //....
    public virtual IList<RestaurantType> Types { get; set; }
}

RestaurantType 的代码是:

public class RestaurantType
{
    [Key]
    public int ID { get; set; }

    [Required]
    public string Type { get; set; }

    public virtual Restaurant Restaurant { get; set; }
}

当我尝试从上下文中删除 restaurant 时,我收到以下错误:

The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.RestaurantTypes_dbo.Restaurants_Restaurant_ID". The conflict occurred in database "aspnet-Test-20131111052251", table "dbo.RestaurantTypes", column 'Restaurant_ID'. The statement has been terminated.

我有生产中的数据,我想尽可能安静地处理它。我尝试了以下代码:

            for (int i = 0; i < restaurant.Types.Count; i++)
            {
                var type = restaurant.Types[i];
                db.RestaurantTypes.Remove(type);
                restaurant.Types.Remove(type);
            }

            db.Restaurants.Remove(restaurant);
            await db.SaveChangesAsync();

但我得到了同样的错误。我检查了数据库,没有包含餐厅 ID 的行。我什至试过这个:

        var list = db.RestaurantTypes.Where(t => t.Restaurant == null || t.Restaurant.ID == restaurant.ID);
        foreach (var ib in list)
        {
            db.RestaurantTypes.Remove(ib);
        }
        db.SaveChanges();

它也没有工作。我有办法用 C# 代码解决这个问题吗?

【问题讨论】:

  • 为什么餐厅有餐厅类型列表?可以是多种类型吗?另外,为什么餐厅类型会引用餐厅?
  • @TimSchmelter 餐厅有一个类型列表,是的。将其视为某种类别。例如,一家餐厅既可以是意大利餐厅,也可以是印度餐厅!我们的系统需要它。起初对restaurant 的引用不可用。我刚刚添加了它来编写最后一个sn-p。 (检查Restaurant 字段是否为NULL)无论它是否存在,我都会收到错误。

标签: c# asp.net sql-server asp.net-mvc entity-framework


【解决方案1】:

根据您的模型,Remove 可能实际上不会删除 RestaurantTypes 中的行。尝试改用 DeleteObject(请参阅 Entity Framework .Remove() vs. .DeleteObject())。还要确保在删除所有 RestaurantTypes 之前没有删除 Restaurant,请尝试在删除所有 RestaurantTypes 后提交更改:

for (int i = 0; i < restaurant.Types.Count; i++)
{
    var type = restaurant.Types[i];
    db.DeleteObject(type);
    restaurant.Types.Remove(type);
}
db.SaveChanges();

db.DeleteObject(restaurant);
db.SaveChanges();

另外,附带说明(这与您的错误消息无关):您的数据库模型中的关系不是倒退的。如果一个 Restaurant 可以有一个或多个 RestaurantTypes,你应该有一个从 Restaurant 到 RestaurantTypes 的引用。这意味着您需要一个保存关系的附加表(例如 RelRestaurantRestaurantType):

---------------                      ------------------                          ------------------ 
|             |                      | Rel            |                          |                |
| Restaurant  | <-- Restaurant_ID -- | Restaurant     | -- RestaurantType_ID --> | RestaurantType |
|             |                      | RestaurantType |                          |                |
---------------                      ------------------                          ------------------

按照您的操作方式,每个餐厅都有自己的类型副本。例如。假设你有一个类型“Chinese”,你有 100 家中国餐馆。然后,您的表 RestaurantType 中会出现 100 个“Chinese”条目。

【讨论】:

    【解决方案2】:

    质疑你的逻辑(餐厅和餐厅类型),餐厅应该是餐厅类型的孩子。

    您正在尝试做的是级联删除 要得到这个,你应该在两个表中都有键

    public class Restaurant{
        public Restaurant()
        {
            Types=new List<RestaurantType>();
        }
        [Key]
        public int Id{get; set;}
        [Required]
        public string Name{get; set;}
    
        public virtual ICollection<RestaurantType> Types{get;set;}
    }
    
    public class RestaurantType{
       [Key]
       public int Id{get;set;}
       [Required]
       public string Type{get; set;}
       public int RestaurantId{get; set;}
    
       [ForeignKey("RestaurantId")]
       public Restaurant Restaurant{get;set;}    
    }
    

    并且您的代码将正确执行 但请确保您的逻辑是正确的,实际上据我所知,这家餐厅只有一种类型,而且数量不多

    问候

    【讨论】:

    • 其实我觉得你的代码差别不大。唯一的变化是您添加了 EF 从类定义中推断出的 ForeignKey 属性。只是为了确定,我可以测试它。您确定这是我收到此错误的原因吗?
    • 我忘了提及,有时您需要删除实体状态,这样您可以确保 EF 将使用以下方法删除行:db.Entity(type).State=EntityState。已删除; ...希望对您有所帮助
    猜你喜欢
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多