假设我在ASP.NET MVC代码第一种方法中有以下模型:
public class City
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Restaurant
{
public int Id { get; set; }
public int CityId { get; set; }
public virtual City City { get; set; }
}
这意味着我有一个名为City
的表,其中包含:
另一个名为Restaurant
的表格包含:
City
表中的外键重新标识ID,删除时没有级联)现在因为我的城市数据是固定的而且变化不大,我使用种子方法来填充它:
context.Cities.AddOrUpdate(x => x.Name,
new City() { Name = "Springfield" },
new City() { Name = "Franklin" },
new City() { Name = "Greenville" }
);
请注意我没有分配任何ID,因为City Id是一个身份字段并且自动递增。
我担心的一个场景是这样的:
假设Restaurant
表中有一些餐馆引用这些城市。现在随着时间的推移,由于某些未知原因,Franklin
的Id为2会从City
表中删除。因此,当您注意到发生了什么时,再次将Franklin
作为城市插入,但这次它的ID已经更改。那么那些已经将“富兰克林”称为他们的城市的餐馆会发生什么呢?
我应该使City Id不是一个身份主键,而只是一个整数主键并自己分配City ID吗?
如果我在外键上启用级联删除,那么我将丢失引用已删除城市的记录,我不希望这样。我想保留它们,直到我弄清楚删除的城市发生了什么并解决问题。
所以有了这些信息,就我而言,从身份字段制作外键是一个好习惯吗?处理这种情况的最佳方法是什么?
答案 0 :(得分:4)
主键和外键确保称为“参照完整性”。就像听起来一样,它们确保了数据中包含的引用的完整性。如果你在一个城市有餐馆,你不应该被允许删除那个城市,因为它会破坏引用的完整性(即你现在有孤儿餐馆)。另一种方法是,如果删除城市,则允许数据库删除餐馆。这些场景中的任何一种(阻止删除或级联删除)都可以使用外键完成。
每当一个表中的数据依赖于另一个表中的数据时,您应该创建一个外键,以确保不会导致数据损坏。它是一个标识列的事实是无关紧要的。
您的数据库是防御损坏数据的最后一道防线。您希望确保不允许导致删除行的“未知原因”。首先防止问题比在数据损坏后尝试修复数据更容易。
答案 1 :(得分:1)
只要有餐厅引用它,您就无法从表格中删除任何城市。
这将由外键强制执行。 (您可以在创建外键时自定义此项:ON DELETE CASCADE,ON DELETE SET NULL ...)
所以答案是肯定的:这是一个很好的做法。