2013-03-15 111 views
3

我一直在使用Dapper.NET一段时间了。我只是想知道是否可以让Dapper修剪字符串,因为它将它们分配给对象的属性。修剪字符串与Dapper.NET

我目前在属性设置器中使用SQL中的LTRIM(RTRIM(fieldname))和/或value.Trim()

但是我使用的是使用字符而不是varchar的遗留数据库,我想知道是否有办法减少我不得不修剪所有内容的时间。

我有一个通过编辑短小精悍的源代码,自己去了,但最终打破其他映射等这么屈服了。

如果任何人有可能减少这方面的开销有任何建议只是想知道。 (我可能会错过一些非常简单的东西!)

我正在用C#3.5顺便说一句。

+0

什么数据库你在使用它的'传统名称'访问? Interbase的? ...等 – MethodMan 2013-03-15 15:56:00

+0

道歉,其实际MS SQL服务器。 – Moffmo 2013-03-15 16:14:29

+0

那么你是在寻找一个全面的属性设置器,但是在服务器上的LTRIM(RTRIM(...))的性能,使得查询每次都会在服务器端自动修剪? – Todd 2013-03-16 03:48:17

回答

6

我不喜欢小巧玲珑修改的想法直。我决定通过创建一个扩展方法来解决Dapper的问题,并仅仅反映结果并修剪所有字符串属性来解决问题。

public static class DapperExtensions { 
    public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) { 
     var dapperResult = SqlMapper.Query<T>(cnn, sql, param, transaction, buffered, commandTimeout, commandType); 
     var result = TrimStrings(dapperResult.ToList()); 
     return result; 
    } 

    static IEnumerable<T> TrimStrings<T>(IList<T> objects) { 
     //todo: create an Attribute that can designate that a property shouldn't be trimmed if we need it 
     var publicInstanceStringProperties = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType == typeof (string) && x.CanRead && x.CanWrite); 
     foreach (var prop in publicInstanceStringProperties) { 
      foreach (var obj in objects) { 
       var value = (string) prop.GetValue(obj); 
       var trimmedValue = value.SafeTrim(); 
       prop.SetValue(obj, trimmedValue); 
      } 
     } 
     return objects; 
    } 

    static string SafeTrim(this string source) { 
     if (source == null) { 
      return null; 
     } 
     return source.Trim(); 
    } 
} 

至关重要的我的解决方案(因为我想用相同的名称小巧玲珑)是扩展方法的分辨率是如何工作的,你可以阅读有关here

+0

我不敢相信我其实没有想到这个!我实际上也为自己实施了自己的包装,但还有其他的东西。我没有想到在那里做字符串修剪! – Moffmo 2015-04-27 08:44:46

1

我假设您想要一种更自然的方式来通过您的POCO暗示LTRIM(RTRIM())函数,以便您不必每次都要手动输入LTRIM(RTRIM())时该字段,无需手动重复劳动即可为您提供SQL性能。

我对你有两种选择:

在小巧玲珑的 - 点 - 网侧:

你可以就在查询功能阶段添加一些代码,对原始SQL执行替换算法查询。

  • 如果您在查询多个表,我会考虑这一点的范围
  • 否则,我相信这可以很容易不破坏短小精悍引擎的其余部分来完成。

过程:

  • 首先在你的表名执行一个无知的IndexOf,不区分大小写,因此您可以通过通做一个快速的,如果它不是。
  • 如果找到表名,那么执行一些更可靠的查询分析,确保您发现的表名实际上是查询中的表名。在这里,您还可以确保查询中只有一个表并且没有连接。
  • 如果在Select a *,这可以扩展到基于你的POCO定义
  • 所以,现在你只要在你的选择阵容
  • 对于所有字段的字段的字段名,在选择阵容,发现在你的POCO定义,那里是一个[裁剪]属性的名称,以及LTRIM(RTRIM({字段名}))为[{字段名}]替换字段名

在SQL端:

如果您有权创建在服务器上的视图,然后你可以编写一个存储过程来创建/更改(更新)一组视图,这些视图暴露了char字段的varchar接口。

批量更新 - 运行这个每次有一个架构的变化:1。 遍历所有用户表 2.创建或更新相应的视图

UpdateTableView(表名): 1.退出,如果没有焦炭领域 2,自动化创建的视图与投(LTRIM(RTRIM(..))为varchar(CHAR_FIELD_SIZE)

+0

感谢Todd的建议。一定会试一试。我们的很多查询都使用多个表。但是,如果我们使用了可以工作的观点。我不确定这会影响它的性能。将尝试,看看它是如何去! – Moffmo 2013-03-18 11:15:53

+0

RE:Views - 通常意见可以使表现更好。物化视图允许您在视图上也创建索引。确保何时有模式更改可以“刷新”视图。某些ORM可能无法通过视图回写,特别是如果缺少ID。 – Todd 2013-03-19 00:00:27

1

马特,

这可以很容易的。我做了这个变化来清洁SQL char空间,我已经测试过它如果由于变化导致速度缓慢,我的代码不会显示任何迹象。

第一个确保您备份您的退出源代码,以便在您需要时更容易恢复。

下一页创建以下方法:

public static string ReadString(object value) /*** CUSTOM CODE ***/ 
{ 
    if (value == null || value is DBNull) return null; 
    return value.ToString().Trim(); 
} 

我总是刻度/ *自定义代码我所有的代码更改* /让我以后可以很容易地找到我的变化

下一页找到以下方法:

public static void SetTypeMap(Type type, ITypeMap map) 

现在这种方法找到以下行:

if (memberType == typeof (char) || memberType == typeof (char?)) 
{ 
    il.EmitCall(OpCodes.Call, typeof (SqlMapper).GetMethod(
     memberType == typeof (char) ? "ReadChar" : "ReadNullableChar", 
     BindingFlags.Static | BindingFlags.Public), null); 
     // stack is now [target][target][typed-value] 
} 
else 

,并修改为:

if (memberType == typeof (char) || memberType == typeof (char?)) 
{ 
    il.EmitCall(OpCodes.Call, typeof (SqlMapper).GetMethod(
     memberType == typeof (char) ? "ReadChar" : "ReadNullableChar", 
     BindingFlags.Static | BindingFlags.Public), null); 
     // stack is now [target][target][typed-value] 
} 
else if (memberType == typeof(string)) /*** CUSTOM CODE START ***/ 
{ 
    il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("ReadString", BindingFlags.Static | BindingFlags.Public), null); 
    // stack is now [target][target][typed-value] 
} /*** CUSTOM CODE END ***/ 
else 

编译,你准备好去

+0

这太棒了。我也尝试过编辑SetTypeMap,但是我真的不知道我在用Emit Calls做什么,而且我也无法弄清楚在哪里处理字符串字段。我不能相信你所要做的就是添加另一个! – Moffmo 2014-04-28 13:50:19