【问题标题】:How to get Dapper dynamic as case insensitive?如何让 Dapper 动态不区分大小写?
【发布时间】:2016-06-24 04:00:41
【问题描述】:

我将 Dapper 与 Oracle 一起使用。 Oracle 查询结果列不区分大小写(除非你用双引号括起来),并且 Oracle 以大写形式返回列名。所以当使用动态时,Dapper 需要使用大写的字段名。

有没有办法让 Dapper 在使用 Dynamic 时不关心大小写?我在 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.

【问题讨论】:

  • 我需要为此添加一个设置;问题是其他 ado.net 提供商得到了“正确”,并允许仅按大小写区分名称
  • @MarcGravell - 我看到了 Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;会使它不区分大小写,但如果是这样,我认为这仅用于属性匹配。如果可以选择使用 Dapper 开箱即用地完成这项工作,将会非常有帮助。

标签: c# oracle dapper


【解决方案1】:

编辑:

请参阅this answer 以了解枚举属性以执行类似于我在下面的操作的替代方法(您可以将dynamic 转换为IDictionary<string,object>)。

另外(对 Oracle 不够熟悉,不知道这是否属实)但也许如果您在 SELECT 查询中为列名起别名(即在 T-SQL 中使用 AS)会覆盖大小写?

原文:

(Marc Gravell 说以下内容不适用于 Dapper。)

改编 this answer 的想法是否有效(特别是未经 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;
        }   
    }
}

【讨论】:

  • 那不行; Query 中的对象是真正意义上的dynamic - 要求反射属性是没有意义的
  • 嗨,像 Jared 这样的词,要使用 Oracle 区分大小写,您需要:从 dual 中选择 1 作为“QuotesMakeItCaseSensitive”。只是后来我要转义双引号,sql开始看起来很粗糙,不再是轻量级了。我确实认为我可以在 IDictionary 上创建一个扩展方法,该方法返回一个不区分大小写的 IDictionary。在不改变 Dapper 本身的情况下,这似乎是最好的解决方案。
【解决方案2】:

鉴于查询结果可以转换为IDictionary&lt;string, object&gt;,只需转换每个动态结果,然后调用如下方法:

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.
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 2011-10-14
    • 2012-12-01
    • 2020-02-18
    • 2012-01-03
    • 2013-04-26
    • 2021-10-31
    相关资源
    最近更新 更多