【问题标题】:.NET CORE: Dapper map many-to-many query.NET CORE:Dapper 映射多对多查询
【发布时间】:2020-12-19 19:47:14
【问题描述】:

我正在尝试学习 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);

            }
        }

【问题讨论】:

  • 在 StudentViewModel 构造函数中设置断点。我的猜测是每个 CourseModel 实例都会调用它。见dapper-tutorial.net/query

标签: sql asp.net asp.net-core mapping dapper


【解决方案1】:

在学习使用 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 });

【讨论】:

    猜你喜欢
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 2019-04-07
    • 2010-10-24
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多