Multi-Mapper在Dapper中的一对多关系

时间:2015-08-31 06:26:14

标签: c# asp.net-mvc dapper dapper-extensions

我试图通过一对多的关系来获取我的数据库的值 我有这样的对象

学生

<link href="<?php echo site_url('css/bootstrap.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/add.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/datepicker.css'); ?>" rel="stylesheet">





            <link href="<?php echo site_url('css/jquery-ui.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/jquery-ui.min.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/jquery-ui.structure.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/jquery-ui.structure.min.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/jquery-ui.theme.css'); ?>" rel="stylesheet">
            <link href="<?php echo site_url('css/jquery-ui.theme.min.css'); ?>" rel="stylesheet">



            <link href="<?php echo site_url('/bower_components/metisMenu/dist/metisMenu.min.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('/dist/css/timeline.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('/dist/css/sb-admin-2.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('/bower_components/morrisjs/morris.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('bower_components/font-awesome/css/font-awesome.min.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('bower_components/metisMenu/dist/metisMenu.min.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('bower_components/datatables-responsive/css/dataTables.responsive.css'); ?>" rel="stylesheet">

            <link href="<?php echo site_url('/bower_components/bootstrap/dist/css/bootstrap.min.css'); ?>" rel="stylesheet">


            <link rel="shortcut icon" href="<?php echo site_url('img/favicon.ico'); ?>" type="image/x-icon" />


            <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>




                        <script>
                        $(function()
                        {
                            $('#spinnerInput').spinner();
                        });
                        </script>








            <script src="http://code.jquery.com/jquery-latest.js"></script>
            <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>



        <script src="<?php echo site_url('js/bootstrap.min.js'); ?>"></script>
        <script src="<?php echo site_url('css/external/jquery/jquery.js'); ?>"></script>
        <script src="<?php echo site_url('bower_components/metisMenu/dist/metisMenu.min.js'); ?>"></script>
        <script src="<?php echo site_url('/bower_components/datatables/media/js/jquery.dataTables.min.js'); ?>"></script>
        <script src="<?php echo site_url('/bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js'); ?>"></script>
        <script src="<?php echo site_url('/dist/js/sb-admin-2.js'); ?>"></script>






            <script src="<?php echo site_url('bower_components/bootstrap/dist/js/bootstrap.min.js');?>"></script>

            <script src="<?php echo site_url('bower_components/metisMenu/dist/metisMenu.min.js');?>"></script>


            <script src="<?php echo site_url('bower_components/raphael/raphael-min.js');?>"></script>

            <script src="<?php echo site_url('js/morris-data.js');?>"></script>

            <script src="<?php echo site_url('dist/js/sb-admin-2.js');?>"></script> 




          <script>
            $(document).ready(function() {
                $('#dataTables-example').DataTable({
                        responsive: true
                });
            });
            </script>

注册

[Table("Student")]
    public class Student  : IStudent
    {    

        public int Id { get; set; }
        public string Lastname { get; set; }
        public string FirstMidName { get; set; }
        public DateTime? EnrollmentDate { get; set; }

        [Write(false)]
        public IEnumerable<Enrollment> Enrollments { get; set; }
    }

[Table("Enrollment")]
    public class Enrollment
    {
        public int Id { get; set; }
        public int CourseId { get; set; }
        public int StudentId { get; set; }
        public string Grade { get; set; }
        public virtual Course Course { get; set; }
        public virtual Student Student { get; set; }
    }

这是我的短小精悍的代码

[Table("Course")]
public class Course
{   
    public int Id { get; set; }
    public string Title { get; set; }
    public int Credits { get; set; }
    public virtual IEnumerable<Enrollment> Enrollments { get; set; }
}

根据指令Here我所要做的就是扩展3级层次结构,但我不能让它工作

这是我的带有映射器的GridReader

_connection = Connect.GetOpenConnection();
        const string query = @"SELECT * FROM Student stu where id = @id " +
                             "SELECT * FROM Enrollment enr WHERE enr.StudentId in (SELECT id FROM Student stu where id = @id) " +
                             "SELECT * FROM Course cou WHERE cou.Id in (SELECT CourseId from Enrollment where StudentId = @id)";

        var result = _connection.QueryMultiple(query, new { id = id })
            .Map<Student, Enrollment, Course, int>(
                student => student.Id,     
                enrollment => enrollment.StudentId,
                course=>course.Id,
                (student, enrollments) => student.Enrollments = enrollments ,
                (student, courses) => student.Enrollments.ForEach(s=>courses.ForEach(x=>s.Course.Title = x.Title) )
            ).FirstOrDefault();

当我在这里运行我的应用程序时,ID为1的结果通知课程标题没有值。我希望你能帮助我,谢谢你。 failed

更新1

我注意到我在这里得到空值,它没有进入if语句

public static IEnumerable<TFirst> Map<TFirst, TSecond, TThird, TKey>
        (
        this SqlMapper.GridReader reader,
        Func<TFirst, TKey> firstKey,
        Func<TSecond, TKey> secondKey,
        Func<TThird, TKey> thirdKey,
        Action<TFirst, IEnumerable<TSecond>> addSecond,
        Action<TFirst, IEnumerable<TThird>> addThird
        )
    {
        var result = reader.Read<TFirst>().ToList();

        var secondMap = reader
            .Read<TSecond>()
            .GroupBy(s=>secondKey(s))
            .ToDictionary(g => g.Key, g => g.AsEnumerable());

        var thirdMap = reader
           .Read<TThird>()
           .GroupBy(t => thirdKey(t))
           .ToDictionary(g => g.Key, g => g.AsEnumerable());     


        foreach (var item in result)
        {
            IEnumerable<TThird> third;
            if (thirdMap.TryGetValue(firstKey(item), out third))
            {
                addThird(item, third);
            }

            IEnumerable<TSecond> second;
            if (secondMap.TryGetValue(firstKey(item), out second))
            {
                addSecond(item, second);
            }

        }



        return result.ToList();
    }

更新2

我在这里解决的问题是我做的事情

IEnumerable<TSecond> second;
        if (secondMap.TryGetValue(firstKey(item), out second))
        {
            addSecond(item, second);
        }

请注意,我添加了var ctr = 0; var mapped2 = conn.QueryMultiple(query, new {id}) .Map<Student, Enrollment, Course, int>( student => student.StudentId, enrollment => ctr = enrollment.StudentId, course=>course.CourseId = ctr, ((student, enrollments) => { student.Enrollments = enrollments; }), ((student, courses) => courses.ToList().ForEach(s=> student.Enrollments.ToList().ForEach(x=>x.Course = new Course { Title = s.Title })))); 以获取ctrCourseId的值。 好了,我现在面临另一个问题,如何获得enrollment => ctr = enrollment.StudentId的值 这是我的代码

  

((学生,课程)=&gt; courses.ToList()。ForEach(s =&gt; student.Enrollments.ToList()。ForEach(x =&gt; x.Course = new Course                       {                           Title = s.Title                       }))

我只获得最后一个值

1 个答案:

答案 0 :(得分:0)

以下是我解决问题的方法

如上面的更新2 详细信息,我添加了一个变量ctr,以便从CourseId获取Enrollment的值并传递给Course得到正确的价值。在那之后,我面临另一个问题,如何从Course Student.Enrollment.Course传递var enrollLst = new List<Enrollment>();的值,这是我如何理解的。

我创建了一个变量Enrollment来保存第一个动作中((student, enrollments) => { enrollLst = enrollments.ToList(); }), 的值

((student, courses) =>
                {
                    var ctrId = 0;  
                    courses.ToList().ForEach(cour =>
                    {
                        if (cour != null)
                        {
                            enrollLst[ctrId].Course = cour;
                            ctrId++;
                        }
                        else
                        {
                            enrollLst[ctrId].Course = null;
                            ctrId++;
                        }   
                    });
                    student.Enrollments = enrollLst;
                })).FirstOrDefault(); 

第二行动

_connection = Connect.GetOpenConnection();
        const string query = "SELECT * from Student stu where StudentId = @id  " +
                             "SELECT * from Enrollment enr where enr.StudentId in ( SELECT StudentId from Student stu where Studentid = @id)  " +
                             "SELECT * FROM Course cou WHERE cou.CourseId in (SELECT CourseId from Enrollment where StudentId = @id)";

        var enrollLst = new List<Enrollment>();
        var ctr = 0;
        var result = _connection.QueryMultiple(query, new { id })
            .Map<Student, Enrollment, Course, int>(
                student => student.StudentId,
                enrollment => ctr = enrollment.StudentId,
                course => course.CourseId = ctr,
                ((student, enrollments) =>
                {
                    enrollLst = enrollments.ToList();
                }),
                ((student, courses) =>
                {
                    var ctrId = 0;  
                    courses.ToList().ForEach(cour =>
                    {
                        if (cour != null)
                        {
                            enrollLst[ctrId].Course = cour;
                            ctrId++;
                        }
                        else
                        {
                            enrollLst[ctrId].Course = null;
                            ctrId++;
                        }   
                    });
                    student.Enrollments = enrollLst;
                })).FirstOrDefault(); 

下面是我的整个代码

public static IEnumerable<TFirst> Map<TFirst, TSecond, TThird, TKey>
        (
        this SqlMapper.GridReader reader,
        Func<TFirst, TKey> firstKey,
        Func<TSecond, TKey> secondKey,
        Func<TThird, TKey> thirdKey,
        Action<TFirst, IEnumerable<TSecond>> addSecond,
        Action<TFirst, IEnumerable<TThird>> addThird
        )
    {
        var result = reader.Read<TFirst>().ToList();

        var secondMap = reader
            .Read<TSecond>()
            .GroupBy(secondKey)
            .ToDictionary(g => g.Key, g => g.AsEnumerable());

        var thirdMap = reader
           .Read<TThird>()
           .GroupBy(thirdKey)
           .ToDictionary(g => g.Key, g => g.AsEnumerable());     

        foreach (var item in result)
        {
            IEnumerable<TSecond> second;
            if (secondMap.TryGetValue(firstKey(item), out second))
            {
                addSecond(item, second);
            }

            IEnumerable<TThird> third;
            if (thirdMap.TryGetValue(firstKey(item), out third))
            {
                addThird(item, third);
            }  
        }  
        return result.ToList();
    }

带有映射器的GridReader,按照指示here

扩展了3级层次结构
{{1}}