EF如何拥有一对一,多对一的关系?

时间:2017-11-16 17:10:48

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

上下文

我正在使用实体框架核心代码的第一种方法。实体框架核心位于.Net核心类库中。

情况:

关系

我有一个名为Question的表和一个名为AnswerOption的表。这些表具有如下关系:

  • Question有一个RightAnswer,类型为AnswerOption
  • Question可以有更多AnswerOptions

一个问题有多个答案选项,其中一个是正确的答案。

代码

public class Question
{
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public int Id { get; set; }

     public virtual AnswerOption RightAnswerId { get; set; }
     public virtual AnswerOption RightAnswer { get; set; }

     public virtual ICollection<AnswerOption> AnswerOptions { get; set; } 
}

public class AnswerOption
{
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public int Id { get; set; }               

     public int QuestionId { get; set; }

     public virtual Question Question { get; set; }
}

问题

创建数据库时,会抛出以下错误:

  

&#39;无法确定导航所代表的关系   property&#39; AnswerOption.Question&#39;类型&#39;问题&#39;。手动   配置关系,或使用。忽略此属性   &#39; [NotMapped]&#39;属性或使用&#39; EntityTypeBuilder.Ignore&#39;在   &#39; OnModelCreating&#39;&#39;

我已尝试在DbContext类的OnModelCreating()方法中手动设置关联版本entity framework relationship builder,但不完全知道如何使此关系起作用。< / p>

如何在这些表之间声明一对一和多对一关系?

1 个答案:

答案 0 :(得分:1)

以下是在EF Core中如何做到这一点。 AnswerOption应该有一个复合键来提高性能,因此您可以强制确定问题的RightAnswer必须是该问题的AnswerOptions之一,这需要EF Core中的流畅配置。否则你只需要注释ForeignKey和InverseProperty,并使RightAnswerId可以为空,这样你就可以插入一个没有RightAnswer的问题。

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
//using Microsoft.Samples.EFLogging;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;


namespace EFCore2Test
{
    public class Question
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public virtual int? RightAnswerId { get; set; }

        [ForeignKey("Id,RightAnswerId")]
        public virtual AnswerOption RightAnswer { get; set; }

        public virtual ICollection<AnswerOption> AnswerOptions { get; set; }
    }

    public class AnswerOption
    {       
        public int QuestionId { get; set; }

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

        [InverseProperty("AnswerOptions")]
        public virtual Question Question { get; set; }
    }
    public class Db : DbContext
    {
        public DbSet<Question> Questions { get; set; }
        public DbSet<AnswerOption> AnswerOptions { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<AnswerOption>().HasKey(e => new { e.QuestionId, e.Id });
            base.OnModelCreating(modelBuilder);
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Server=(local);Database=Test2;Trusted_Connection=True;MultipleActiveResultSets=true");
            base.OnConfiguring(optionsBuilder);
        }
    }




    class Program
    {


        static void Main(string[] args)
        {
             using (var db = new Db())
            {

                db.Database.EnsureDeleted();
               // db.ConfigureLogging(s => Console.WriteLine(s));
                db.Database.EnsureCreated();
                for (int i = 0; i < 100; i++)
                {
                    var q = new Question();
                    db.Questions.Add(q);

                    var a = new AnswerOption();
                    a.Question = q;
                    var b = new AnswerOption();
                    b.Question = q;
                    db.SaveChanges();

                    q.RightAnswer = a;
                    db.SaveChanges();
                }

            }

            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}