7

我与外键有一对一的关系,但由于Cascade Delete某种原因没有启用。示例代码如下。

public class AppRegistration
{
    public int AppRegistrationId { get; set; }
    [Required]
    [StringLength(50)]
    [Display(Name = "Username")]
    public string UserName { get; set; }
    [Required]
    [StringLength(100)]
    public string Password { get; set; }
    [StringLength(20)]
    public string StudentOrAgent { get; set; }
    // navigation properties
    public virtual AppStatus AppStatus { get; set; }
    public virtual Agreement Agreement { get; set; }
    public virtual AnotherTable AnotherTable { get; set; }
}

具有外键的依赖表如下。

public class Agreement
{
    [Key]
    [ForeignKey("AppRegistration")]
    public int AppRegistrationId { get; set; }
    public DateTime DateAgreed { get; set; }
    public virtual AppRegistration AppRegistration { get; set; }
}

当我尝试从生成的AppRegistrations表中删除一个条目时,我得到一个引用约束冲突。

我尝试[Required]在依赖表中放置导航属性,但它没有做任何事情 - 该Update-Database命令显示No pending code-based migrations.消息。有任何想法吗?谢谢。

更新: 我收到以下错误消息:

The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.AppStatus_dbo.AppRegistrations_AppRegistrationId". The conflict occurred in database "MVCapp", table "dbo.AppStatus", column 'AppRegistrationId'.

4

2 回答 2

9

我决定cascade delete在一个单独的示例项目中解决这个问题。我发现以下博客和 MSDN 页面非常有用。

使用该Code First方法创建以下模型。

public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public virtual Book Book { get; set; }
}
public class Book
{
    public int CategoryId { get; set; }
    public string BookTitle { get; set; }
    public string BookAuthor { get; set; }
    public string BookISBN { get; set; }
    public virtual Category Category { get; set; }
}

(我意识到实体名称暗示了一对多的关系,但我试图模拟一对一的关系,就像我最初的问题一样。)

因此,在上述模型中,每个Category只能有一个Book

在您的DbContext- 派生类中添加以下内容。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<Book>()
        .HasKey(t => t.CategoryId);

    modelBuilder.Entity<Category>()
        .HasRequired(t => t.Book)
        .WithRequiredPrincipal(t => t.Category)
        .WillCascadeOnDelete(true);
}

(上述代码需要以下命名空间:System.Data.Entity, System.Data.Entity.ModelConfiguration.Conventions.)

这正确地创建了一对一的关系。您将在每个表中都有一个主键,并且在启用的Book表中还有一个外键。ON DELETE CASCADE

模型的数据库图

在上面的代码中,在我使用参数的实体Category上,参数是依赖表中的外键列。WithRequiredPrincipal() t => t.Category

如果你WithRequiredPrincipal() 不带参数使用,你会在表中得到一个额外的列,并且Book表中有两个外键Book指向表CategoryIdCategory

我希望这些信息有所帮助。

更新

后来我直接在这里找到了答案:

http://msdn.microsoft.com/en-us/data/jj591620#RequiredToRequired

于 2013-05-12T22:07:09.547 回答
7

你没有得到级联删除的一个原因是你的关系是可选的。

如果您想要所需的关系,即AppRegistration必须有一个Agreement您可以使用的关系(自动配置级联删除):

public class Agreement
{
    ...
    [Required]
    public AppRegistration AppRegistration{ get; set; }
}

如果您希望关系对于级联删除是可选的,您可以使用 Fluent API 进行配置:

modelBuilder.Entity<AppRegistration>()
    .HasOptional(a => a.Agreement)
    .WithOptionalDependent()
    .WillCascadeOnDelete(true);
于 2013-05-10T16:20:48.017 回答