C# 在多对多实体框架应用程序中,通过ID将多个子项添加到父项的最有效方法(创建多个映射)

C# 在多对多实体框架应用程序中,通过ID将多个子项添加到父项的最有效方法(创建多个映射),c#,entity-framework,many-to-many,database-performance,C#,Entity Framework,Many To Many,Database Performance,以本例中的代码为例: 当我有课程ID时,向学生添加多个课程的最有效方法是什么 因此,例如,函数可能如下所示: private static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds) {} public static async Task AddCoursesToStudentAsync(SchoolDBContext context, S

以本例中的代码为例:

当我有课程ID时,向学生添加多个课程的最有效方法是什么

因此,例如,函数可能如下所示:

 private static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds)
    {}
public static async Task AddCoursesToStudentAsync(SchoolDBContext context, Student student, List<int> CourseIds)
    {
        await context.Courses.Where(x => CourseIds.Contains(x.CourseId)).ForEachAsync(x => x.Students.Add(student));
        context.SaveChanges();
    }

    private static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds)
    {
        var task = AddCoursesToStudentAsync(context,student,CourseIds);
        task.Wait();
    }
你会说:

 public static  void AddCoursesToStudentMaps(SchoolDBContext context, Student student, List<int> CourseIds)
    {
        List<StudentCourse> maps = CourseIds.ConvertAll(courseId => new StudentCourse(courseId, student.StudentId)).ToList();
        context.StudentCourses.AddRange(maps);
    }

p、 不只是拥有课程列表的原因是因为我们已经设置了发送id列表的表单/应用程序等,如前所述,将这些模型从数据库中拉出来,仅仅将它们添加到父对象中,似乎既愚蠢又低效

我不认为隐式链接表的多对多是代码优先的。另外,虽然它使查询更容易、更自然,但正如您已经看到的那样,当使用链接修改时,它有明显的缺点

通过使用存根实体,可以高效地实现添加新链接:


我不认为带有隐式链接表的
多对多
是代码优先的。另外,虽然它使查询更容易、更自然,但正如您已经看到的那样,当使用链接修改时,它有明显的缺点

通过使用存根实体,可以高效地实现添加新链接:


对于这样一个简单的问题,你的问题太多了。另外,如果你需要每门课程的学生名单,你希望如何在不去数据库获取该课程的情况下获取该名单?这就是为什么多对多关系总是用第三实体建模的原因。抱歉,我只是想展示它的工作性,但很明显这会误导你,因为你误解了我的问题,我不需要课程,我已经有了课程ID,只想添加“链接”,正如你所说,它通常是用第三实体建模的,但是EF可以在“引擎盖下”创建所述链接表,但在我的具体情况下,除非我忽略EFs内置功能并创建自己的第三实体,否则似乎效率低下。对于这样一个简单的问题,您的问题有太多的文本。另外,如果你需要每门课程的学生名单,你希望如何在不去数据库获取该课程的情况下获取该名单?这就是为什么多对多关系总是用第三实体建模的原因。抱歉,我只是想展示它的工作性,但很明显这会误导你,因为你误解了我的问题,我不需要课程,我已经有了课程ID,只想添加“链接”,正如你所说,它通常是用第三实体建模的,但EF可以“在引擎盖下”帮助创建链接表,但在我的具体情况下,除非我忽略EFs内置功能并创建自己的第三个实体,否则效率似乎很低,只是想知道(可能还有很长的路要走),但这不是一对多关系吗?我不确定EF内部是如何做到这一点的,但如何将多个添加到一侧(即将课程分配给学生)将多个添加到另一侧(即将新学生分配给每门课程)?1-例如,上下文在使用块中,这在网络项目上是如何工作的?2-你的意思是学生已经存在于数据库中,或者已经在这个上下文中被修改/特别地从数据库中退出context@chrispepper1989它与典型的Web控制器操作一起工作,这些操作分配db上下文、执行某些操作并对其进行处理(或在
中使用
块,如您所述)。它不适用于用于许多操作的长期上下文。@CamiloTerevinto不,此技巧适用于多对多。您可以使用任何一方的
icoloction
导航属性向另一方添加链接。
Attach
用于告诉EF
课程是现有的(否则它将尝试添加新的
课程
和链接)。感谢您的编辑,谢谢!只是想知道(可能有点遥远),但这不是一对多关系吗?我不确定EF内部是如何做到这一点的,但如何将多对一添加(即将课程分配给学生)呢将多个添加到另一侧(即将新学员分配到每门课程)?1-例如,上下文在使用块中,这在web项目中如何工作?2-你的意思是学生已经存在于数据库中,或者已经在该上下文中被修改/专门从数据库中拉出context@chrispepper1989它与典型的Web控制器操作一起工作,这些操作分配db上下文、执行某些操作和显示ose它(或在
中使用您提到的
块)。它不适用于用于许多操作的长期上下文。@CamiloTerevinto不,此技巧适用于多对多。您可以使用任何一方的
icoloction
导航属性向另一方添加链接。
Attach
用于告诉EF
课程是现有的(否则将尝试添加新的
课程
和链接)。感谢您的编辑,谢谢!
 public static  void AddCoursesToStudentMaps(SchoolDBContext context, Student student, List<int> CourseIds)
    {
        List<StudentCourse> maps = CourseIds.ConvertAll(courseId => new StudentCourse(courseId, student.StudentId)).ToList();
        context.StudentCourses.AddRange(maps);
    }
 static void Main(string[] args)
    {
        Run();
    }

    private static void Run()
    {
        using (SchoolDBContext context = new SchoolDBContext())
        {
            /* Run once
             * SetUp(context);
             */
            Test(context);
            Output(context);
        }
    }

    static void SetUp(SchoolDBContext context)
    {
        context.Students.Add(new Student() { StudentName = "Gerry" });
        context.Students.Add( new Student() { StudentName = "Bob" }  );
        context.Students.Add( new Student() { StudentName = "Jane" } );

        context.Courses.Add( new Course() { CourseName = "Science" });
        context.Courses.Add( new Course() { CourseName = "Math" }  );
        context.Courses.Add( new Course() { CourseName = "History" } );
        context.Courses.Add(new Course() { CourseName = "Other History" });
        context.Courses.Add(new Course() { CourseName = "Roman History" });
        context.Courses.Add(new Course() { CourseName = "English History" });
        context.Courses.Add(new Course() { CourseName = "Super History" });
        context.Courses.Add(new Course() { CourseName = "Tudor History" });
        context.Courses.Add(new Course() { CourseName = "Queen History" });
        context.Courses.Add(new Course() { CourseName = "King History" });
        context.SaveChanges();
    }

    public static void Test(SchoolDBContext context)
    {

        var ids = context.Courses.Where(x => x.CourseName.Contains("History")).Select(x => x.CourseId).ToList();
        var student = context.Students.FirstOrDefault(x => x.StudentName == "Bob");
        AddCoursesToStudent(context, student, ids);
    }

    private static void Output(SchoolDBContext context)
    {
        OutputStudents(context);
    }

    private static void OutputStudents(SchoolDBContext context)
    {
        var allStudents = context.Students.ToList();
        foreach (var student in allStudents)
        {
            Console.WriteLine($"Student: {student.StudentName}");
            if (student.Courses.Any())
            {
                Console.WriteLine("is enrolled on");
                Console.WriteLine("**************************");
                foreach (var contextCourseStudent in student.Courses)
                {
                    Console.WriteLine("     " + contextCourseStudent.CourseName);
                }
                Console.WriteLine("************************ ");
            }
            Console.WriteLine("-------------------------");
        }
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
    private static void OutputCourse(SchoolDBContext context)
static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds)
{
    student.Courses = CourseIds.Select(id => context.Courses.Attach(new Course { CourseId = id })).ToList();
    context.SaveChanges();
}
public void AddCoursesToStudent(int studentId, List<int> coursesIds)
{
    using (var context = new SchoolDBContext())
    {
        var student = context.Students.Find(studentId);
        AddCoursesToStudent(context, student, coursesIds);
    }
}