使用多列密钥删除实体框架级联

时间:2013-08-19 21:45:47

标签: c# entity-framework ef-code-first

我已经设置了这些模型:

public class Advisor
    {
    public virtual int AdvisorId { get; set; }
    public virtual int UserId { get; set; }
    public User User { get; set; }

    public ICollection<AdvisorStudentMap> AdvisorStudentMaps { get; set; }
    }

public class AdvisorStudentMap
{
    [Required]
    public virtual int AdvisorId { get; set; }
    [Required]
    public virtual int UserId { get; set; }
}

public class User
{
    public virtual int UserId { get; set; }
    public virtual string UserName { get; set; }
    public virtual string FirstName { get; set; }
    public ICollection<AdvisorStudentMap> AdvisorStudentMaps { get; set; }
}

在我的OnModelCreating中我有:

modelBuilder.Entity<AdvisorStudentMap>()
    .HasKey(t => new {t.AdvisorId, t.UserId});

在我的流畅api中,如何设置它以便在删除顾问程序时删除AdvisorStudentMap?我一直收到错误消息:Message =在'AdvisorStudentMaps'表上引入FOREIGN KEY约束'FK_dbo.AdvisorStudentMaps_dbo.Users_UserId'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。 无法创建约束。查看以前的错误。

更新 - 同样在OnModelCreating我有:

modelBuilder.Entity<Advisor>()
.HasRequired(t => t.AdvisorStudentMaps).WithMany().WillCascadeOnDelete(true);

由此我得到错误'级联外键'FK_dbo.Advisors_dbo.AdvisorStudentMaps_AdvisorId_UserId'无法在引用列'Advisors.AdvisorId'是标识列的位置创建。

2 个答案:

答案 0 :(得分:1)

您似乎试图模拟学生和顾问之间的多对多关系。这就是你通常这样做的方式:

public class Advisor
 {
    //Key fields don't need to be marked virtual
    public int AdvisorId { get; set; }

    //If you want the property to lazy load then you should mark it virtual
    public virtual ICollection<Student> Students{ get; set; }

    //Advisors have a UserProfile
    public int UserProfileId{get;set;}
    public virtual UserProfile UserProfile {get; set;}    
}

public class Student
{
    public int StudentId { get; set; }
    public virtual ICollection<Advisor> Advisors { get; set; }

    //Students also have a UserProfile
    public int UserProfileId{get;set;}
    public virtual UserProfile UserProfile {get; set;}
}

public class UserProfile
{
   public int UserProfileId{get;set;}

   //NB not marked virtual - that is only needed on navigation properties when 
   //we want to use lazy loading
   public string UserName {get;set}
   public string FirstName {get;set}
}

实体框架将自动创建连接表以建模关系。除非需要为关系添加属性,否则不需要AdvisorStudentMap实体。

关于删除问题的级联。如果删除用户,则可以级联到Student表和Advisor表。从Student到StudentAdvisorMap有一个级联路径,另一个从Advisor到StudentAdvisorMap。因此,多个级联路径。 Sql Server不允许这样做。您必须explicitly implement代码中的删除才能避免此

答案 1 :(得分:1)

我在此链接的帮助下想出了这一点:http://blog.cdeutsch.com/2011/09/entity-framework-code-first-error-could.html 正如他在博客上所说的那样,它不是很直观,但是这里的语法是有效的:

modelBuilder.Entity<AdvisorStudentMap>()
            .HasRequired(u=>u.User)
            .WithMany(m=>m.AdvisorStudentMaps)
            .WillCascadeOnDelete(false);