C# 如何建立一对一和多对一的关系?
上下文: 我正在使用实体框架核心代码优先的方法。实体框架核心位于.Net核心类库中 情况: 关系 我有一个名为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;
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();
}
}
}