使用代码修复"DELETE语句与REFERENCE约束冲突"错误

Ali*_*ori 3 c# sql-server asp.net asp.net-mvc entity-framework

我有一个Asp.Net MVC 5网站,其中包含EntityFramework Code First.在我的网站中,我有一个Restaurant包含以下代码的模型:

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

    //....
    public virtual IList<RestaurantType> Types { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

而代码RestaurantType是:

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

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

    public virtual Restaurant Restaurant { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试删除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();
Run Code Online (Sandbox Code Playgroud)

但我得到了同样的错误.我检查了数据库,没有餐馆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();
Run Code Online (Sandbox Code Playgroud)

它也没用.有没有办法让我用C#代码解决这个问题?

nha*_*rer 6

根据您的型号,删除可能实际上不会删除RestaurantTypes中的行.请尝试使用DeleteObject(请参阅Entity Framework .Remove()与.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();
Run Code Online (Sandbox Code Playgroud)

此外,在旁注(这与您的错误消息无关):数据库模型中的关系不是倒退.如果餐厅可以有一个或多个餐厅类型,您应该有从餐厅到餐厅类型的参考.这意味着您需要一个包含关系的附加表(例如RelRestaurantRestaurantType):

---------------                      ------------------                          ------------------ 
|             |                      | Rel            |                          |                |
| Restaurant  | <-- Restaurant_ID -- | Restaurant     | -- RestaurantType_ID --> | RestaurantType |
|             |                      | RestaurantType |                          |                |
---------------                      ------------------                          ------------------
Run Code Online (Sandbox Code Playgroud)

你这样做的方式,每个餐厅都有它自己的类型副本.例如,假设你有一个"中国人"类型,你有100家中国餐馆.那么你最终会在你的餐桌餐厅中输入100个"中文"条目.