我正在使用Dapper和Oracle。Oracle 查询结果列不区分大小写(除非将它们双引号括起来),Oracle 以大写形式返回列名。 因此,在使用动态时,Dapper 需要使用大写字段名称。
有没有办法让 Dapper 在使用动态时不关心大小写?我在DapperTable http://dapper-dot-net/Dapper/SqlMapper.DataTable.cs 中看到它使用带有StringComparer.Ordinal而不是StringComparer.OrdinalIgnoreCase的字典,并且我没有看到任何更改它的选项。但我希望有人对此有解决方案,或者可以告诉我如何以更好的方式做到这一点。
例:
var r = cnn.Query("select 'apple' fruit from dual").FirstOrDefault();
var f = r.Fruit; // f is set to null, but I want it to be "apple"
var F = r.FRUIT; // F is set to "apple", but I don't want to reference using all caps.
编辑:
请参阅此答案,也许是一种枚举属性以执行类似于我在下面执行的操作的替代方法(您可能可以将dynamic
转换为IDictionary<string,object>
)。
另外(对 Oracle 不够熟悉,不知道这是否属实),但如果您在 SELECT 查询中为列名设置别名(即在 T-SQL 中使用AS
)可能会覆盖大小写?
源语言:
(Marc Gravell说以下内容不适用于Dapper。
从这个答案中改编的想法是否有效(特别是未经 Dapper 测试)?
using NUnit.Framework;
using System;
using System.Collections.Generic;
namespace StackOverflowSandbox
{
public class ToDictionaryTests
{
[Test]
public void ItShouldWork()
{
// Arrange
var dapperResult = new
{
UPPER = 1,
lower = 2
};
// Act
var dictionary = dapperResult.ConvertToDictionary();
// Assert
Assert.That(dictionary["Upper"], Is.EqualTo(1));
Assert.That(dictionary["Lower"], Is.EqualTo(2));
}
}
public static class ObjectExtensions
{
private static readonly StringComparer ToDictionaryDefaultComparer =
StringComparer.OrdinalIgnoreCase;
/// <summary>
/// Converts an object's properties that can be read
/// to an IDictionary.
/// </summary>
public static IDictionary<string, object> ConvertToDictionary(
this object @this,
StringComparer comparer = null)
{
// The following is adapted from:
// https://stackoverflow.com/a/15698713/569302
var dictionary = new Dictionary<string, object>(
comparer ?? ToDictionaryDefaultComparer);
foreach(var propertyInfo in @this.GetType().GetProperties())
{
if (propertyInfo.CanRead &&
propertyInfo.GetIndexParameters().Length == 0)
{
dictionary[propertyInfo.Name] =
propertyInfo.GetValue(@this, null);
}
}
return dictionary;
}
}
}
假设查询结果可以强制转换为IDictionary<string, object>
,所需要的只是每个动态结果的强制转换,然后调用如下方法:
public static IDictionary<string, T> ToCaseInsensitiveDictionary<T>(this IDictionary<string, T> source)
{
var target = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
foreach (var entry in source)
{
target[entry.Key] = entry.Value;
}
return target;
}
示例用法:
var results = connection.Query(sql);
foreach (IDictionary<string, object> rawResult in results)
{
var result = rawResult.ToCaseInsensitiveDictionary();
var column = result["MY_COLUMN"]; // or result["My_Column"] etc.
}