小巧玲珑.映射到SQL列,列名称中包含空格

Roh*_*ner 18 c# dapper dapper-rainbow

我已经成功地将今天的东西作为小沙箱/ 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]
Run Code Online (Sandbox Code Playgroud)

我的班级看起来像这样

    public class ClassA
    {          
        public string Col1 { get; set; }    

        public string Col2 { get; set; }

        ///... etc
     }
Run Code Online (Sandbox Code Playgroud)

我的实现目前看起来像这样

 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;
  }
Run Code Online (Sandbox Code Playgroud)

注意:SQL无法以任何方式进行修改.

目前我正在经历一个精巧的代码,我唯一可预见的解决方案是添加一些代码来"说服"列比较,但到目前为止没有太多运气.

我在StackOverflow上看到过像dapper扩展这样的东西,但是我希望我能在没有添加扩展的情况下完成这项工作,如果没有的话.我会采取最快捷的方式来实施.

Mar*_*ell 12

这里的一个选择是通过动态/非通用API,然后通过IDictionary<string,object>API每行获取值,但这可能有点单调乏味.

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

SqlMapper.SetTypeMap(typeof(ClassA), new RemoveSpacesMap());
Run Code Online (Sandbox Code Playgroud)

有:

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; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*ney 10

有一个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()));
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅https://github.com/henkmollema/Dapper-FluentMap.


Sha*_*aun 5

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

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; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)