在不使用实体框架的多对多中插入记录

Posted

技术标签:

【中文标题】在不使用实体框架的多对多中插入记录【英文标题】:Insert records in many to many not working with Entity Framework 【发布时间】:2016-02-27 11:41:34 【问题描述】:

我想在他们的表中插入 2 条新记录,并创建多对多关系。

这个主题有很多问题,我尝试了很多答案,现在我不知道为什么我的代码不起作用。

请帮帮我!

这是代码:

class Program

    static void Main(string[] args)
    
        MyContext db = new MyContext();

        var st1 = new Student()  Name = "Joe" ;
        var c1 = new Course()  Name = "Math" ;

        db.Courses.Attach(c1);
        st1.Courses.Add(c1);
        db.Students.Add(st1);         

        db.SaveChanges();            
           

public class Student

 public Student()
    
        Courses = new HashSet<Course>();
    
    public int Id  get; set; 
    public string Name  get; set; 
    public virtual ICollection<Course> Courses  get; set; 

public class Course

    public int Id  get; set; 
    public string Name  get; set; 
    public virtual ICollection<Student> Students  get; set; 

public class MyContext : DbContext

    public DbSet<Student> Students  get; set; 
    public DbSet<Course> Courses  get; set; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        modelBuilder.Entity<Student>()
            .HasMany(p => p.Courses)
            .WithMany(d => d.Students)
            .Map(t =>
            
                t.MapLeftKey("studentId");
                t.MapRightKey("courseid");
                t.ToTable("StudentCourse");
            );

        base.OnModelCreating(modelBuilder);
    


编辑:像建议的那样,我初始化了课程:

 public Student()
    
        Courses = new HashSet<Course>();
    

现在我在 db.SaveChanges() 上收到此错误;

保存不为其关系公开外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地处理保存时的异常。有关详细信息,请参阅 InnerException。

【问题讨论】:

What is a NullReferenceException and how do I fix it?的可能重复 您的 st1 不是 EF 包装器 - 它只是 Student 类型的对象,并且 Student 类不会初始化其 Courses 集合。 我怎样才能让它工作? 用一些new List&lt;Student&gt;() 或其他东西初始化Courses 集合。 【参考方案1】:

您显然正试图将新的Student 添加到数据库并将其与现有 Course 相关联。问题是您在没有正确主键的情况下将新的Course 实体附加到上下文。

在这里使用所谓的存根实体当然是个好主意,因为它节省了到数据库的往返以获取现有的Course,但EF需要主键创建正确的关联记录。它甚至是您需要在此 Course 存根中设置的唯一属性:

var st1 = new Student()  Name = "Joe" ;
var c1 = new Course()  CourseId = 123 ;

db.Courses.Attach(c1);
st1.Courses.Add(c1);
db.Students.Add(st1);         

如果你想添加新课程和新学生,你应该Add他们两个:

db.Courses.Add(c1);
st1.Courses.Add(c1);
db.Students.Add(st1);        

【讨论】:

两个值(st1,c1)都是新值,在数据库中不存在,是的,我试图在所有 3 个表中插入这 2 个新值。有可能吗? 现在正在工作:),我尝试了很多组合,只有这个没有:) @Arnold 您能否在评论中编辑您的答案,因为我将您的答案标记为已接受。谢谢 我已经做到了。我只是展示了这两种可能性,以使答案更适用于未来的访问者。【参考方案2】:

您的代码未在任一类中初始化 ICollection 对象。

public class Student

    private Student()
    
        Courses = new List<Course>();
    

    public int Id  get; set; 
    public string Name  get; set; 
    public virtual ICollection<Course> Courses  get; set; 

编辑

尝试将您的模型构建器代码更改为以下内容

modelBuilder.Entity<Student>()
            .HasMany<Course>(s => s.Courses)
            .WithMany(c => c.Students)
            .Map(cs =>
                    
                        cs.MapLeftKey("StudentRefId");
                        cs.MapRightKey("CourseRefId");
                        cs.ToTable("StudentCourse");
                    );

代码示例直接取自:

http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx

【讨论】:

我得到了同样的错误'new List();'我在编辑中发布的 0 我删除了数据库,并根据您建议的配置更改重新创建了数据库,但出现了同样的错误,就像我在编辑中发布的那样。

以上是关于在不使用实体框架的多对多中插入记录的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL 和 Linq 的多对多关系(实体框架/实体)

多对多实体框架和存储库模式插入/更新

实体框架中的多对多关系导致无限循环

实体框架更改生成的多对多表的名称

Remove() 不适用于实体框架中的多对多关系

SQLAlchemy如何在多对多中按孩子过滤