C# 如何建立一对一和多对一的关系?

C# 如何建立一对一和多对一的关系?,c#,entity-framework,ef-code-first,entity-framework-core,C#,Entity Framework,Ef Code First,Entity Framework Core,上下文: 我正在使用实体框架核心代码优先的方法。实体框架核心位于.Net核心类库中 情况: 关系 我有一个名为Question的表和一个名为AnswerOption的表。这些表具有如下关系: 问题有一个正确答案,属于回答选项类型 问题可以有更多的答案选项 一个问题有多个答案选项,其中一个是正确答案 代码 公开课问题 { [数据库生成(DatabaseGeneratedOption.Identity)] 公共int Id{get;set;} 公共虚拟应答选项RightAnswerId{get;

上下文:

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

情况:

关系

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

  • 问题
    有一个正确答案,属于
    回答选项类型
  • 问题
    可以有更多的
    答案选项
一个问题有多个答案选项,其中一个是正确答案

代码

公开课问题
{
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
公共虚拟应答选项RightAnswerId{get;set;}
公共虚拟应答选项RightAnswer{get;set;}
DbContext类的
OnModelCreating()
方法中的公共虚拟ICollection,但不知道如何使此关系正常工作


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

以下是如何在EF Core中实现这一点。AnswerOption应该有一个用于性能的复合键,因此您可以强制要求问题的正确答案必须是该问题的AnswerOption之一,这需要在EF Core中进行流畅的配置。否则,您可以只需注释ForeignKey和InverseProperty,并使RightAnswerId为null,这样就可以插入一个没有正确答案的问题

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();
        }
    }
}
使用Microsoft.EntityFrameworkCore;
使用制度;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
//使用Microsoft.Samples.EFLogging;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.ComponentModel.DataAnnotations;
命名空间EFCore2Test
{
公开课问题
{
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
公共虚拟int?RightAnswerId{get;set;}
[ForeignKey(“Id,RightAnswerId”)]
公共虚拟应答选项RightAnswer{get;set;}
公共虚拟ICollection应答选项{get;set;}
}
公共类应答选项
{       
public int QuestionId{get;set;}
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
[反向属性(“应答选项”)]
公共虚拟问题{get;set;}
}
公共类Db:DbContext
{
公共数据库集问题{get;set;}
公共数据库集应答选项{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasKey(e=>new{e.QuestionId,e.Id});
基于模型创建(modelBuilder);
}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
optionsBuilder.UseSqlServer(“服务器=(本地);数据库=测试2;可信连接=真;MultipleActiveResultSets=真”);
基本配置(选项生成器);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
使用(var db=new db())
{
db.Database.EnsureDeleted();
//db.ConfigureLogging(s=>Console.WriteLine);
db.Database.recreated();
对于(int i=0;i<100;i++)
{
var q=新问题();
db.问题。添加(q);
var a=新的应答选项();
a、 问题=q;
var b=新的应答选项();
b、 问题=q;
db.SaveChanges();
q、 RightAnswer=a;
db.SaveChanges();
}
}
Console.WriteLine(“按任意键退出”);
Console.ReadKey();
}
}
}

为什么要使用此选项:
公共虚拟应答选项RightAnswerId{get;set;}
?检查此RightAnswerId是否为RightAnswerId,然后它的类型可能应为
int
string
,如下面的答案所示。谢谢!!,准备尝试一下,我知道了这个错误的原因:
来自“无法保存更改,因为在要保存的数据中检测到循环依赖关系:”ForeignKey:问题{'Id',RightAnswerId'}->AnswerOption{'QuestionId',Id'}TopPrincipal:RightAnswer,ForeignKey:AnswerOption{'QuestionId'}->问题{'Id'}->ToDependent:AnswerOptions-TopPrincipal:Question'.
看起来您没有将AnswerOption配置为具有复合键:
modelBuilder.Entity().HasKey(e=>new{e.QuestionId,e.Id});
播放时有点像您所说的那样进行了更改,但随后出现了此错误(请参见上文)。表之间存在循环依赖关系。是的。模型中存在循环。对于SQL Server,这意味着您必须先插入问题和答案,然后返回并在后续命令中设置正确答案。使用完整的工作示例更新了答案。
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();
        }
    }
}