我一直在使用Dapper.NET
一段时间了。我只是想知道是否有可能让Dapper修剪字符串,因为它将它们分配给对象的属性。
我目前在SQL中使用LTRIM(RTRIM(fieldname))
,在属性设置器中使用value.Trim()
。
然而,我正在使用使用chars而不是varchar的遗留数据库,我想知道是否有办法减少我必须修剪所有内容的时间。
我通过编辑dapper的源代码来完成自己,但最终打破了其他映射等所以放弃了。
只是想知道是否有人有任何可以减少这种开销的建议。 (我可能会遗漏一些非常简单的东西!)
顺便说一句,我正在使用C#3.5。
答案 0 :(得分:7)
我不喜欢直接修改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();
}
}
我的解决方案至关重要(因为我想使用与Dapper相同的名称)是扩展方法解析的工作原理,您可以阅读here。
答案 1 :(得分:1)
我假设你想要一种更自然的方式来通过你的POCO暗示LTRIM(RTRIM())函数,这样你每次想要返回时都不需要手动输入LTRIM(RTRIM())字段,在没有手动重复劳动的情况下为您提供SQL性能。
我有两种选择:
在Dapper-Dot-Net方面:
您可以在查询功能阶段添加一些代码,在原始SQL查询上执行替换算法。
过程:
在SQL端:
如果您有权在服务器上创建视图,那么您可以编写存储过程来创建/更改(更新)一组视图,这些视图公开了char字段的varchar接口。
批量更新 - 每次有架构更改时运行此命令: 1.遍历所有用户表 2.创建或更新相应的视图
UpdateTableView(表名): 1.如果没有字段,则退出 2.使用强制转换(LTRIM(RTRIM(...))作为varchar(CHAR_FIELD_SIZE)自动创建视图
答案 2 :(得分:1)
马特,
这可以很容易地完成。我做了这个更改来清理SQL char空间。我测试了它,我的代码显示没有迹象表明由于变化导致的缓慢。
首先确保您备份现有的源代码,以便在需要时更容易恢复。
下一步创建以下方法:
public static string ReadString(object value) /*** CUSTOM CODE ***/
{
if (value == null || value is DBNull) return null;
return value.ToString().Trim();
}
我总是用/ * CUSTOM CODE * /标记我的所有代码更改,以便稍后我可以轻松找到我的更改
下一步找到以下方法:
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
编译,你准备好了