C# 使用Dapper.NET修剪字符串

C# 使用Dapper.NET修剪字符串,c#,sql,dapper,C#,Sql,Dapper,我已经使用了Dapper.NET一段时间了。我只是想知道是否有可能让Dapper在将字符串分配给对象属性时修剪字符串 我目前在SQL中使用LTRIM(RTRIM(fieldname)),在属性设置器中使用value.Trim() 然而,我正在使用一个使用chars而不是varchar的遗留数据库,我想知道是否有一种方法可以减少我修剪所有内容的时间 我自己尝试过编辑dapper的源代码,但最终破坏了其他映射等,所以放弃了 我只是想知道是否有人有任何建议可以减少这种开销。(我可能遗漏了一些非常简单的

我已经使用了
Dapper.NET
一段时间了。我只是想知道是否有可能让Dapper在将字符串分配给对象属性时修剪字符串

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

然而,我正在使用一个使用chars而不是varchar的遗留数据库,我想知道是否有一种方法可以减少我修剪所有内容的时间

我自己尝试过编辑dapper的源代码,但最终破坏了其他映射等,所以放弃了

我只是想知道是否有人有任何建议可以减少这种开销。(我可能遗漏了一些非常简单的东西!)


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

我假设您希望通过POCO使用更自然的方式来暗示LTRIM(RTRIM())函数,这样您就不需要在每次希望返回该字段时手动输入LTRIM(RTRIM()),从而在不需要手动重复劳动的情况下获得SQL性能

我有两个选择:

在整洁的点网方面:

您可以在查询函数阶段添加一些代码,对原始SQL查询执行替换算法

  • 如果查询中有多个表,我会考虑范围之外的
  • 否则,我相信这可以很容易地完成,而不会中断其他整洁的引擎
过程:

  • 首先在表名上执行一个不知道的IndexOf,忽略大小写,以便在不知道的情况下快速通过
  • 如果找到了表名,则对查询执行更可靠的分析,确保找到的表名实际上是查询中的表名。在这里,您还可以确保查询中只有一个表,并且没有联接
  • 如果select上有*,则可以根据您的poco定义将其扩展为字段名
  • 因此,现在您只需在select队列中设置字段
  • 对于所有字段,在选择列表中,在poco定义中找到名称,其中有[Trim]属性,将字段名称替换为LTRIM(RTRIM({FieldName}))作为[{FieldName}]
在SQL端:

如果您有权在服务器上创建视图,那么您可以编写一个存储过程来创建/更改(更新)一组视图,这些视图为char字段公开varchar接口

批更新-每次架构更改时都运行此更新: 1.循环浏览所有用户表 2.创建或更新相应的视图

UpdateTableView(表名): 1.如果没有字符字段,则退出 2.自动创建视图,并将强制转换(LTRIM(RTRIM(..)作为varchar(CHAR\u FIELD\u SIZE)

Matt

这是很容易做到的。我做这个更改是为了清理SQL字符空间。我已经对它进行了测试,我的代码没有显示由于更改而导致的速度变慢的迹象

首先确保备份现有源代码,以便在需要时更容易恢复

下一步创建以下方法:

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

编译后就可以开始了

我不喜欢直接修改Dapper的想法。我决定创建一个扩展方法来包装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();
    }
}
公共静态类DapperExtensions{
公共静态IEnumerable查询(此IDbConnection cnn,字符串sql,对象参数=null,IDbTransaction transaction=null,bool buffered=true,int?commandTimeout=null,CommandType?CommandType=null){
var dapperResult=SqlMapper.Query(cnn、sql、参数、事务、缓冲、命令超时、命令类型);
var result=TrimStrings(dapperResult.ToList());
返回结果;
}
静态IEnumerable字符串(IList对象){
//todo:创建一个属性,该属性可以指定在需要时不应修剪属性
var publicInstanceStringProperties=typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)。其中(x=>x.PropertyType==typeof(string)&&x.CanRead&&x.CanWrite);
foreach(publicInstanceStringProperties中的var prop){
foreach(对象中的var obj){
var value=(字符串)prop.GetValue(obj);
var trimmedValue=value.SafeTrim();
道具设定值(obj、trimmedValue);
}
}
归还物品;
}
静态字符串SafeTrim(此字符串源){
if(source==null){
返回null;
}
返回source.Trim();
}
}

对我的解决方案至关重要(因为我想使用与Dapper相同的名称)是扩展方法解析的工作原理,您可以阅读。

关于它的
Legacy name
Access?Interbase?…etcApologies,它实际上是MS SQL Server。那么,除了LTRIM(RTRIM(…)的性能,您在寻找什么样的数据库在服务器上,这样每次查询都会在服务器端自动修剪?感谢您的建议Todd。我一定会尝试一下。我们的许多查询确实使用多个表。但是如果我们使用可以工作的视图,我不确定这会对其性能产生多大影响。我将尝试看看它是如何运行的!RE:views-通常,视图可以提高性能。物化视图还允许您在视图上创建索引。确保在架构发生更改时“刷新”视图。某些ORM可能无法通过视图进行回写,尤其是在缺少ID的情况下。这太棒了。我尝试编辑SetTyp