.NET CORE:Dapper映射多对多查询

问题描述

我正在尝试学习Dapper,并且在尝试将查询映射到多对多关系时遇到了麻烦。在这种情况下,我有三个模型和各自的表,CourseModel,StudentCourseModel和Studentviewmodel。

我正在尝试创建一个详细视图,您可以在其中显示学生的所有课程。这就是我试图访问数据的方式,但是由于某种原因,即使学生参加的课程多于课程,但在学生课程列表中仅设置了一个“课程”记录。我究竟做错了什么?谢谢!

课程模型

    public class CourseModel
    {
        public int Id { get; set; }
        public string CourseCode { get; set; }
        public string CourseName { get; set; }
        public string CourseDescription{ get; set; }

    }

StudentCourseModel

    public class StudentCourseModel
    {
        public int Id { get; set; }
        public int StudentId { get; set; }
        public int CourseId { get; set; }
    }

Studentviewmodel

    public class Studentviewmodel
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public List<CourseModel> Courses { get; set; }

        public Studentviewmodel()
        {
            Courses = new List<CourseModel>();
        }
    }
        public async Task<IActionResult> Details(int id)
        {
            using (IDbConnection cnn = new sqlConnection("Data Source=(localdb)\\MSsqlLocalDB;Initial Catalog=SchoolSystemDB;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultisubnetFailover=False"))
            {
                var p = new
                {
                    Id = id
                };

                string sql = $@"select dbo.Students.*,dbo.Courses.*
                            from dbo.Students
                            INNER JOIN[dbo].[StudentCourses] ON dbo.StudentCourses.StudentID = dbo.Students.Id
                            INNER JOIN[dbo].[Courses] ON dbo.Courses.Id = dbo.StudentCourses.CourseId
                            WHERE dbo.Students.Id = @Id";

                Studentviewmodel student = cnn.Query<Studentviewmodel,CourseModel,Studentviewmodel>(sql,(Studentviewmodel,CourseModel) =>
                    {
                        Studentviewmodel.Courses.Add(CourseModel);
                        return Studentviewmodel;
                    },p).First();

                return View(student);

            }
        }

解决方法

当我学会使用dapper时,我还遇到了多对多映射的问题。

对我来说,以下程序证明是有用的:

构建映射函数时,您可以在数据库建模工具(例如 SSMS )中执行一次查询,以查看查询数据的结构。

然后,您可以想象对于查询结果中返回的每一行,都将执行映射功能。因此,您需要跟踪映射功能已经处理的数据。传递给函数的StudentViewModel实例代表当前行之一,这说明了为什么只附加一门课程。

要跟踪学生,可以在映射功能之外使用查找词典。 (无法在atm下测试示例)

    var studentLookup = new Dictionary<int,StudentViewModel>();
    
    var res = cnn
        .Query<StudentViewModel,CourseModel,StudentViewModel>(
           sql,(svm,cm) =>
           {
               // Check if the student was already processed; if so,retrieve the reference
               if (!studentLookup.TryGetValue(svm.Id,out var student))
               {
                   student = svm;
                   studentLookup.Add(svm.Id,student);
               }
    
               // add course to the student that is assigned with the current record
               if (svm.Courses == null)
               {
                   svm.Courses = new List<CourseModel>();
               }
                            
               if (svm.Courses.All(x => x.Id != cm.Id))
               {
                   svm.Courses.Add(cm);
               }
                            
               return svm;
           },new { Id = id });