Dapper查询结果在对象中将表的Pk设置为null

时间:2019-03-30 17:01:06

标签: c# dapper

我正在尝试使用dapper从mysql数据库检索数据,但是结果将id(主键)和外键设置为null。其他属性具有值。

我试图将SQL查询从选择*从课程更改为完整格式,作为选择ID,名称,从课程的ID。

    Course{
        public Course()
        {

        }
        public string Id { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }
        public bool Is_Elective { get; set; }
        public string DId { get; set; }
        public int Sem { get; set; }

    }

   class CourseDAO
    {
        private readonly MySqlConnection conn;
        private string connectionString = "Server=localhost;Database=university;Uid=root;Pwd=*****;";

        public CourseDAO()
        {
            conn = new MySqlConnection(connectionString);
        }

        public List<Course> getAll()
        {
            string sql = "select * from university.course";
            List<Course> courses = conn.Query<Course>(@sql).ToList();
            return courses;
       }
   }

Course Schema

预期: 课程列表中所有来自db的课程都具有正确的值。

实际 课程列表包含db中所有ID为ID的课程,并且为null,其余则具有值。

1 个答案:

答案 0 :(得分:2)

即使Maxim通过问题注释解决了问题,我也想用很少的解决方案来描述问题。

问题原因:

Dapper执行从SQL查询结果到对象按名称的映射。 SQL查询结果字段“标题”会自动映射到Course.Title(映射不区分大小写- )。

在您的情况下,数据库列与C#属性之间存在两个名称不匹配的情况:(course_id!= Iddepartment_id!= DId),因此是Dapper无法映射这些字段。

解决方案1,sql列别名

您可以按照以下方式在sql查询中列出具有可能的列别名的表列:

string sql = "select course_id Ad Id, title, credits, Is_elective, department_id as DId, sem from university.course";

在sql中使用显式列名,Dapper可以执行基于名称的自动映射。

解决方案2,Dapper自定义映射

Dapper Custom mapping是为每个对象手动定义哪个列映射到哪个属性的功能。

这里是处理映射的类(从another SO answer借用的双向映射的思想):

    public class ColumnMap
    {
        private readonly Dictionary<string, string> mappings = new Dictionary<string, string>();

        public void Add(string t1, string t2)
        {
            mappings.Add(t1, t2);
        }

        public string this[string index]
        {
            get
            {
                // Check for a custom column map.
                if (forward.ContainsKey(index))
                    return forward[index];
                if (reverse.ContainsKey(index))
                    return reverse[index];

                // If no custom mapping exists, return the value passed in.
                return index;
            }
        }
    }

设置ColumnMap对象,并告诉Dapper使用该映射。

var columnMap = new ColumnMap();
columnMap.Add("Id", "course_id");
columnMap.Add("DId", "department_id");

SqlMapper.SetTypeMap(typeof (Course), new CustomPropertyTypeMap(typeof (Course), (type, columnName) => type.GetProperty(columnMap[columnName])));

解决方案3,动态类型和LINQ 您可以使用动态对象执行字段映射,如下所示:

string sql = "select * from university.course";
List<Course> courses = conn.Query<dynamic>(@sql)
   .Select(item => new Course()
   {
     Id = item.course_id,
     Title = item.title,
     Credits = item.credits,
     Is_Elective = item.Is_elective,
     DId = department_id,
     Sem = sem
   })
   .ToList();