小巧玲珑。映射到列名中带有空格的 SQL 列

Posted

技术标签:

【中文标题】小巧玲珑。映射到列名中带有空格的 SQL 列【英文标题】:Dapper. Map to SQL Column with spaces in column names 【发布时间】:2013-02-11 15:12:29 【问题描述】:

我今天作为小型沙盒/POC 项目设法启动并运行了一些东西,但似乎在一个问题上碰到了我的头......

问题:

有没有办法让 dapper 映射到带有空格的 SQL 列名。

我的结果集有这样的效果。

例如:

SELECT 001 AS [Col 1], 
       901 AS [Col 2],
       00454345345345435349 AS [Col 3],
       03453453453454353458 AS [Col 4] 
FROM [Some Schema].[Some Table]

我的班级应该是这样的

    public class ClassA
              
        public string Col1  get; set;     

        public string Col2  get; set; 

        ///... etc
     

目前我的实现是这样的

 public Tuple<IList<TClass>, IList<TClass2>> QueryMultiple<TClass, TClass2>(object parameters)
 
      List<TClass> output1;
      List<TClass2> output2;

      using (var data = this.Connection.QueryMultiple(this.GlobalParameter.RpcProcedureName, parameters, CommandType.StoredProcedure))
      
           output1 = data.Read<TClass>().ToList();
           output2 = data.Read<TClass2>().ToList();
      

      var result = new Tuple<IList<TClass>, IList<TClass2>>(output1, output2);
      return result;
  

注意:不能以任何方式修改 SQL。

目前我正在浏览精巧的代码,我唯一可预见的解决方案是添加一些代码来“说服”列比较,但到目前为止还没有太多运气。

我在 *** 上看到有一些类似 dapper 扩展的东西,但我希望我可以在不添加扩展的情况下完成这项工作,如果没有的话。我会采取最快的实施方式。

【问题讨论】:

我也有同样的需求。我通过为查询中的所有列添加别名来解决它,但这非常乏味。下面的解决方案可能有效,但如果 Dapper 可以添加一个属性/参数来忽略空格,而不是每个人都必须添加客户映射器,那就太好了。这些是合法名称,它应该能够轻松映射它们。 这是迄今为止我找到的最好的解决方案:***.com/a/34856158/5504438 【参考方案1】:

有一个 nuget 包 Dapper.FluentMap 允许您添加列名映射(包括空格)。类似于EntityFramework。

// Entity class.
public class Customer

    public string Name  get; set; 


// Mapper class.
public class CustomerMapper : EntityMap<Customer>

    public CustomerMapper()
    
        Map(p => p.Name).ToColumn("Customer Name");
    


// Initialise like so - 
FluentMapper.Initialize(a => a.AddMap(new CustomerMapper()));

请参阅https://github.com/henkmollema/Dapper-FluentMap 了解更多信息。

【讨论】:

@David,我初始化了 FluentMapper。但这似乎不起作用。我想我错过了一些东西。如果我当前的代码是return connection.Query&lt;Customer&gt;("SELECT 'My Name' [Customer Name]").First();,您能否详细说明如何使它工作,如何使它工作以返回客户对象? @user007 你能告诉我你的客户课程吗?你在哪里做映射? @DavidMcEleney,我使用了与您完全相同的 Customer 类。您能否详细说明您在哪里以及如何编写FluentMapper.Initialize(a =&gt; a.AddMap(new CustomerMapper())); 我创建了一个新类,如下所示:public class DapperFluentMapInitializer public static void Init() FluentMapper.Initialize(a =&gt; a.AddMap(new CustomerMapper())); @user007 大约 5 个月前,所以我的记忆有点生疏 - 你在写什么样的应用程序?例如。如果是 Web 应用程序,请打开 Global.asax 并将其添加到 Application_Start 事件中......【参考方案2】:

这里的一个选项是通过动态/非通用 API,然后通过每行的 IDictionary&lt;string,object&gt; API 获取值,但这可能有点乏味。

作为替代方案,您可以创建一个自定义映射器,并将其告诉 dapper;例如:

SqlMapper.SetTypeMap(typeof(ClassA), new RemoveSpacesMap());

与:

class RemoveSpacesMap : Dapper.SqlMapper.ITypeMap


    System.Reflection.ConstructorInfo SqlMapper.ITypeMap.FindConstructor(string[] names, Type[] types)
    
        return null;
    

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetConstructorParameter(System.Reflection.ConstructorInfo constructor, string columnName)
    
        return null;
    

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetMember(string columnName)
    
        var prop = typeof(ClassA).GetProperty(columnName.Replace(" ", ""));
        return prop == null ? null : new PropertyMemberMap(columnName, prop);
    
    class PropertyMemberMap : Dapper.SqlMapper.IMemberMap
    
        private string columnName;
        private PropertyInfo property;
        public PropertyMemberMap(string columnName, PropertyInfo property)
        
            this.columnName = columnName;
            this.property = property;
        
        string SqlMapper.IMemberMap.ColumnName
        
            get  throw new NotImplementedException(); 
        

        System.Reflection.FieldInfo SqlMapper.IMemberMap.Field
        
            get  return null; 
        

        Type SqlMapper.IMemberMap.MemberType
        
            get  return property.PropertyType; 
        

        System.Reflection.ParameterInfo SqlMapper.IMemberMap.Parameter
        
            get  return null; 
        

        System.Reflection.PropertyInfo SqlMapper.IMemberMap.Property
        
            get  return property; 
        
    

【讨论】:

谢谢!我不得不暂时删除 dapper,因为它是一个小的(匆忙的)概念证明所需要的。但我确实喜欢这个框架/库,我绝对认为我会重新添加它。 啊.. 看着这个我想我需要在RemoveSpacesMap 中实现 FindConstructor 方法,对吧?哎呀!对不起。 复制你的默认实现就可以了:return typeof(ClassA).GetConstructor(new Type[0]).. 应该在发布之前多花点时间;对不起。 我正在尝试这个解决方案。它要求我实施FindExplicitConstructor()。有什么建议吗?【参考方案3】:

在尝试通过调用系统 sp_spaceused 过程获取映射结果时,我遇到了类似的问题。 Marc 的代码不太适合我,因为它抱怨无法找到默认构造函数。我还使我的版本通用,因此理论上可以重复使用。这可能不是执行速度最快的代码,但它适用于我,而且在我们的情况下,这些调用很少发生。

class TitleCaseMap<T> : SqlMapper.ITypeMap where T: new()

    ConstructorInfo SqlMapper.ITypeMap.FindConstructor(string[] names, Type[] types)
    
        return typeof(T).GetConstructor(Type.EmptyTypes);
    

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetConstructorParameter(ConstructorInfo constructor, string columnName)
    
        return null;
    

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetMember(string columnName)
    
        string reformattedColumnName = string.Empty;

        foreach (string word in columnName.Replace("_", " ").Split(new[]  ' ' , StringSplitOptions.RemoveEmptyEntries))
        
            reformattedColumnName += char.ToUpper(word[0]) + word.Substring(1).ToLower();
        

        var prop = typeof(T).GetProperty(reformattedColumnName);

        return prop == null ? null : new PropertyMemberMap(prop);
    

    class PropertyMemberMap : SqlMapper.IMemberMap
    
        private readonly PropertyInfo _property;

        public PropertyMemberMap(PropertyInfo property)
        
            _property = property;
        
        string SqlMapper.IMemberMap.ColumnName
        
            get  throw new NotImplementedException(); 
        

        FieldInfo SqlMapper.IMemberMap.Field
        
            get  return null; 
        

        Type SqlMapper.IMemberMap.MemberType
        
            get  return _property.PropertyType; 
        

        ParameterInfo SqlMapper.IMemberMap.Parameter
        
            get  return null; 
        

        PropertyInfo SqlMapper.IMemberMap.Property
        
            get  return _property; 
        
    

【讨论】:

以上是关于小巧玲珑。映射到列名中带有空格的 SQL 列的主要内容,如果未能解决你的问题,请参考以下文章

Excel从列到列的映射

名称中带有空格的 SQLite 列

如果列中存在数据,如何将列名映射到查询响应中?

SQL:如何找到视图列到表列的映射?

使用 flex 实现四列到列列表的反馈 - 第 2 轮

sql server中的表行到列