简体   繁体   中英

make both models aware of each other with a one-to-one relationship in asp.net entity framework

I am unable to get the one to one relationship with EF to work properly. I've scored blogs, SO, and msdn docs, but nothing I do seems to work.

I have two models, a Class and an Exam that look like the following:

[Table("classes")]
public class Class
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [StringLength(255), Required]
    public string Title { get; set; }

    public virtual Exam Exam { get; set; }
}


[Table("exams")]
public class Exam
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [DisplayFormat(DataFormatString = "{0:h:mm tt}")]
    public DateTime? Time { get; set; }

    public int ClassId { get; set; }
    public virtual Class Class { get; set; }
}

I want to be able to access the exam from the Class and the Class from the Exam, but no matter what I do, I find some error.

Trying to create/run migrations I get the following.

The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

If I add this to my context:

protected override void OnModelCreating(DbModelBuilder builder)
{
     builder.Entity<Exam>()
        .HasRequired(e => e.Class)
        .WithOptional(c => c.Exam);
}

I get the following error:

System.Data.Entity.Infrastructure.DbUpdateException: Entities in 'BenchContext.Exams' participate in the 'Class_Exam' relationship. 0 related 'Class_Exam_Source' were found. 1 'Class_Exam_Source' is expected. ---> System.Data.UpdateException: Entities in 'BenchContext.Exams' participate in the 'Class_Exam' relationship. 0 related 'Class_Exam_Source' were found. 1 'Class_Exam_Source' is expected.

I'm not sure how to tell the fluent api how to correctly foreign key between the two models and nothing I do seems to affect it.

What am I missing?

You are trying to build one-to-one relation through ClassId property in Exam class. That requires ClassId to be unique (= unique constraint) but unique constraint are not supported by EF yet.

The only way EF currently supports real one-to-one relation is by sharing primary key:

[Table("classes")]
public class Class
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [StringLength(255), Required]
    public string Title { get; set; }

    public virtual Exam Exam { get; set; }
}


[Table("exams")]
public class Exam
{
    [Key, ForeignKey("Class")]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    [DisplayFormat(DataFormatString = "{0:h:mm tt}")]
    public DateTime? Time { get; set; }

    public virtual Class Class { get; set; }
}

The Id in Exams table is both PK and FK to Classes table. It cannot have autogenerated value. While this is one-to-one relation it still has 1 - 0..1 multiplicity ( Class can exist without Exam but Exam must have Class ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM