首页 > 解决方案 > Dapper 映射问题

问题描述

我无法让 Dapper 将本地 sqlite Db 中的 sql 结果映射到我们的实体类型对象。

它一直试图将第 n-1 列映射到第 n 列,这会导致它在映射到 DateTime 时死掉(因为前一列不会转换)

异常消息:解析第 2 列时出错(user_pswd_exp_dt=Y - 字符串)

这是一个简化版本,它为我重现了这个问题。

 public class UsrMiniDto : IDto
    {

        [Column( "user_id" )]
        public Int64 UserId { get; set; }

        [Column( "user_active" )]
        public string UserActive { get; set; }

        [Column( "user_pswd_exp_dt" )]
        public DateTime? UserPswdExpDt { get; set; }

        [Column( "add_user" )]
        public string AddUser { get; set; }

        [Column( "add_dt" )]
        public DateTime AddDt { get; set; }


    }


public List<UsrMiniDto> GetMiniUsrByUsrName( string usrName )
        {
            StringBuilder sql = new StringBuilder();

            sql.Append( "SELECT  u.user_id ," );
            sql.Append( "u.user_active ," );
            sql.Append( "u.user_pswd_exp_dt   " );//as UserPswdExpDt
            //sql.Append( ", u.add_user ," );
            //sql.Append( "u.add_dt  " );
            sql.Append( " FROM " );
            sql.Append( " usr u" );
            sql.Append( " WHERE u.user_login_name = :usrName" );

            List<UserInput> listUserInput = new List<UserInput>();
            listUserInput.Add( new UserInput( ":usrName", "System.String", usrName ) );

            ICustomFixSql customFixSql = ObjectFactory.GetInstance<ICustomFixSql>();

            string mainSql = customFixSql.BuildSqlFromUserArgs(sql.ToString(), listUserInput);

            try
            {
                DapperCustomMapping<UsrMiniDto>();
                return SqliteGetList<UsrMiniDto>( mainSql );

            }
            catch ( Exception ex )
            {
                throw;
            }

        }

public virtual List<T> SqliteGetList<T>(string mainSql)
        {
            List<T> x;
            using ( SQLiteConnection connection = GetSqLiteConnection() )
            {
                //dapper
                x = connection.Query<T>( mainSql ).ToList();
            }
            return x;
        }

    protected void DapperCustomMapping<T>()
    {
        // custom mapping
        var map = new CustomPropertyTypeMap(typeof(T),
                                            (type, columnName) => type.GetProperties().FirstOrDefault(prop => GetDescriptionFromAttribute(prop) == columnName));
        SqlMapper.SetTypeMap( typeof( T ), map );

    }



   private string GetDescriptionFromAttribute( System.Reflection.MemberInfo member )// this lets you override bad mappings via teh column attribute - EWB
    {
        if ( member == null ) return null;

        var attrib = (ColumnAttribute)Attribute.GetCustomAttribute(member, typeof(ColumnAttribute), false);
        return attrib == null ? null : attrib.Name;
    }

最初我是默认映射,一旦我打开使用下划线映射的设置就遇到了这个问题(以前根本没有映射)

我尝试重命名列以匹配 Sql 中的 DTo 名称。没有喜悦,那么正如您在上面看到的,我尝试使用 column 属性来指定确切的列,但它仍然错过了将列映射为一个。

这是我的代码生成并在查询方法中传递给 Dapper 的 Sql。

SELECT  u.user_id ,u.user_active ,u.user_pswd_exp_dt    FROM  usr u WHERE u.user_login_name = 'KainJesi' 

这是返回的行。user_id user_active user_pswd_exp_dt
66657 Y 1/1/2099 12:00:00 AM

如您所见,user_active 错误地尝试映射到 UserPswdExpDt。

我是 Dapper 的菜鸟,我真的下载了它并在星期六开始使用它。

我究竟做错了什么?

我在 .Net 4.5.2 中,所以我不能使用 Dapper.Dimplecrud,我们的其他团队似乎就是这样解决这个问题的。

- - - -更新

根据评论,我将其转换为 Linq2sql 中的 ExecuteQuery,因此

public List<UsrMiniDto> GetMiniUsrByUsrName( string usrName )
        {
            StringBuilder sql = new StringBuilder();

            sql.Append( "SELECT  u.user_id as UserId," );
            sql.Append( "u.user_active as UserActive," );
            sql.Append( "u.user_pswd_exp_dt  as UserPswdExpDt " );//as UserPswdExpDt
            //sql.Append( ", u.add_user as AddUser," );
            //sql.Append( "u.add_dt as AddDt " );
            sql.Append( " FROM " );
            sql.Append( " usr u" );
            sql.Append( " WHERE u.user_login_name = :usrName" );

            List<UserInput> listUserInput = new List<UserInput>();
            listUserInput.Add( new UserInput( ":usrName", "System.String", usrName ) );

            ICustomFixSql customFixSql = ObjectFactory.GetInstance<ICustomFixSql>();

            string mainSql = customFixSql.BuildSqlFromUserArgs(sql.ToString(), listUserInput);

            try
            {
                //DapperCustomMapping<UsrMiniDto>();
                //return SqliteGetList<UsrMiniDto>( mainSql );
                return SqliteGetList2<UsrMiniDto>( mainSql );


            }
            catch ( Exception ex )
            {
                throw;
            }

        }

public virtual List<T> SqliteGetList2<T>( string mainSql )
        {

            // show complete SQL in log...JK
            INetLog log = ObjectFactory.GetInstance<INetLog>();

            log.Debug( "SqliteGetList<T>(string mainSql = '" + mainSql + "')" );

            List<T> x;
            using ( SQLiteConnection connection = GetSqLiteConnection() )
            {

                //dapper
                //x = connection.Query<T>( mainSql ).ToList();

                //linq 2 sql
                DataContext dc = new DataContext(connection);
                x = dc.ExecuteQuery<T>(mainSql).ToList();
            }
            return x;
        }

我得到异常“字符串未被识别为有效的日期时间。”

这听起来像相同的“Y”被映射到 dateTime 问题。但我仍然不知道为什么将列 n-1 映射到 n.. 非常感谢任何帮助。

注意:这似乎是一个特定于 sqlite 的问题,如果我交换连接以指向我们的一个开发数据库,​​它工作正常。如果我将它指向我的本地 sqlitedb,它会再次崩溃。

标签: c#sqlitedappersystem.data.sqlite

解决方案


推荐阅读