具有代码第一独立关联或外键关联的EF模型

时间:2012-11-17 15:46:35

标签: asp.net-mvc-3 c#-4.0 entity-framework-4 ef-code-first

我从Ladislav读过有关独立协会的文章。我查看了他在link中提供的信息。 这些信息非常有用,并且有所启发。 但是我想建模我可以访问的现有数据库。它有三个表用户,证书和测验。

起初我认为建模是独立的关联。为什么?我的Users表有主键UserID和Certificates表有PK CertID和一列UserID我可以说是外键。就在我认为它是一对多的关系时,我意识到在Certificates表中找不到Users表中的某些UserID。但是,证书中的所有UserID都可以在Users表中找到。

我的问题是我应该使用独立关联,如果是这样,如何实现这一点,我的Users表成为主要类,证书是依赖。这样我可以显示或拥有我的Users表中的值,然后从我的asp.net mvc 3应用程序中的Certificate表中读取值。

请更正下面的代码,其中显示了我打算实现上述目的:

   public class Certificates
{
   [Key]
    public Users CertID { get; set; }
    public int ID { get; set; }
    public DateTime  recvd { get; set; }
    public int QuizID { get; set; }


}

public class Users
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string email { get; set; }
    public ICollection<Certificates> Certificates { get; set; }
}

 public class Quiz
    {
        public int QuizID { get; set; }
        public string QuuizName { get; set; }
        public int VolumeNo { get; set; }
        public int  mark { get; set; }
        public ICollection<Certificates> Certificates { get; set; }
    }

public class cpdContext : DbContext
{
    public DbSet<Certificates> Certificates { get; set; }
    public DbSet<Users> Users { get; set; }
    public DbSet<Users> Quiz { get; set; }

最后,如何使用这三个类的信息显示详细信息视图,并能够添加用户标记和测试。我想要建模的关系在测验和证书之间是1到多。

1 个答案:

答案 0 :(得分:2)

  

我的用户表有主键UserID,证书表有PK   我可以说CertID和一列UserID是外键。正当   我以为它是一对多的关系,我意识到有些UserID   在证书表中找不到用户表。但是所有UserID   在证书中可以在用户表中找到。

对于一对多关系而言,这是很正常的,其中User是主体,而Certificate是依赖关系,并且您对关系强制执行约束。

我不认为这是决定独立或外国关键协会的论据。据我所知,您可以使用两种关联类型映射数据库模式。数据库模式不应该是决策的驱动因素。 Ladislav的帖子链接了所有细节。除了指导决策的数据库模式之外还有其他要点:

  • 架构:严格分离对象和关系世界,这可能导致您不希望“外键”属性作为对象模型中的关系工件。这有利于独立协会。
  • 易用性:在某些情况下,额外的外键属性可以更轻松地处理关系,尤其是更新它们。这一点适用于外键关联。
  • 性能:在某些具有较大型号的情况下,EF与外键关联的速度更快。

就个人而言,上面的第2点在大多数情况下为我提供了尺度,但正如所说的那样是可能的。

使用外键关联进行映射(我省略除PK,FK和导航属性之外的所有属性以保持简短):

public class Certificates
{
    [Key]
    public int CertID { get; set; }

    [ForeignKey("User")]
    public int UserID { get; set; }
    [ForeignKey("Quiz")]
    public int QuizID { get; set; }

    public Users User { get; set; }
    public Quiz Quiz { get; set; }
}

public class Users
{
    public int ID { get; set; }
    public ICollection<Certificates> Certificates { get; set; }
}

public class Quiz
{
    public int QuizID { get; set; }
    public ICollection<Certificates> Certificates { get; set; }
}

这假设两个关系都是必需的,即数据库中的FK不可为空。如果它们是你需要使FK属性也可以为空(int?)。您可以使用Fluent API代替数据注释,与以下示例类似(但不完全相同!)。

与独立协会的映射:

public class Certificates
{
    [Key]
    public int CertID { get; set; }

    public Users User { get; set; }
    public Quiz Quiz { get; set; }
}

public class Users
{
    public int ID { get; set; }
    public ICollection<Certificates> Certificates { get; set; }
}

public class Quiz
{
    public int QuizID { get; set; }
    public ICollection<Certificates> Certificates { get; set; }
}

public class cpdContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entitiy<Users>()
            .HasMany(u => u.Certificates)
            .WithRequired(c => c.User)  // or WithOptional
            .Map(m => m.MapKey("UserID")); //<- DB FK column name

        modelBuilder.Entitiy<Quiz>()
            .HasMany(u => u.Certificates)
            .WithRequired(c => c.Quiz)  // or WithOptional
            .Map(m => m.MapKey("QuizID")); //<- DB FK column name
    }
}

Certificates中的导航属性不是必需的(在第一个和第二个例子中都没有),你可以删除它们,如果你不需要它们,只需使用无参数WithRequired()然后,并在第一个示例中使用Fluent API。 (可能[ForeignKey("UserID")]课程中Certificates集合上的Users注释也可以使用。)