【问题标题】:Change TableAttribute in runtime for Dapper在运行时为 Dapper 更改 TableAttribute
【发布时间】:2018-03-26 11:48:31
【问题描述】:

我使用 DapperTableAttribute

using Dapper.Contrib.Extensions;

namespace MyCompany.Entities
{
    [Table(Config.TABLE_ARCHIVO_CLIENTE)] 
    public partial class ArchivoCliente
    {

工作

  public const string TABLE_ARCHIVO_CLIENTE = "Archivo_Cliente";

如果不是const string,则无法正常工作。我尝试使用static property 来使用appSettings

  public static string TABLE_ARCHIVO_CLIENTE
  {
       get
       {
           return ConfigurationManager.AppSettings.Get(KeyTable);
       }
  }

对于使用 AppSettings 有什么建议吗?

【问题讨论】:

    标签: c# reflection data-annotations dapper custom-attributes


    【解决方案1】:

    属性参数需要常量。

    检查 Dapper.Contrib 代码,非常不寻常地访问属性按名称。如果是按类型,您可以执行以下操作:

    class ConfigTableAttribute : TableAttribute {
        public ConfigTableAttribute(string configSetting)
             : base(LookupTableNameFromConfig(configSetting));
    
        private static string LookupTableNameFromConfig(string configSetting)
        {
            // TODO: your code here
        }
    }
    

    并使用以下代码注释您的代码:

    [ConfigTable(nameof(Config.TABLE_ARCHIVO_CLIENTE))]
    class Foo {}
    

    然后您的工作就是实现 TODO,该 TODO 将通过反射或索引器等获取实际值。在显示的代码中,输入 configSetting 将是 TABLE_ARCHIVO_CLIENTE


    但是,由于它通过 namedynamic 访问它,因此您真正需要的只是 称为 TableAttribute 的东西 具有 Name。您可以执行与上述相同的操作,但在不同的命名空间中:

    namespace MyEvilness {
        class TableAttribute : Attribute {
            public TableAttribute(string configSetting) {
                 Name = LookupTableNameFromConfig(configSetting);
            }
            // etc as before
        }
    }
    

    并使用:

    [MyEvilness.Table(nameof(Config.TABLE_ARCHIVO_CLIENTE))]
    class Foo {}
    

    注意事项;我认为当前的实现是一个错误!我理解为什么它是这样做的(即它可以与 EF 一起使用),但我很想使它适用于 either 方法。

    【讨论】:

    • 您能否详细说明如何确保从配置文件中获取的表名的sql注入安全,或者指出我的方向?
    • @nae 第 1 步:有一个已知表名的列表;第 2 步:检查该列表
    【解决方案2】:

    我写了一个小的package 来解决这个问题。如果键与配置文件中的FullName 匹配,它将值分配为表名。 一些努力避免sql注入。

    可以像依赖注入一样添加它

    // Startup.cs or Program.cs
    // ...
    services.ReadTablenamesFromConfig(configuration.GetSection("MySectionName"));
    // ...
    

    有配置:

    // appsettings.json
    ...
      "MySectionName": {
        "TableNames": {
          "Demo.Sale": "sale_2020"
        }
      },
    ...
    

    对于模型:

    // Sale.cs
    namespace Demo
    {
        //[Table("sale_2020")]
        public class Sale
        {
            public string Product { get; set; }
            public int Quantity { get; set; }
        }
    }
    

    查看更好的示例here


    暂且实现如下:

    // TablenameExtensions.cs
    using Dapper.Contrib.Extensions;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using System;
    
    namespace Dapper.Contrib.Extensions.Tablename
    {
        public static class TablenameExtensions
        {
            private static TablenameConfig _config;
            public static IServiceCollection ReadTablenamesFromConfig(this IServiceCollection services, IConfigurationSection configSection)
            {
                services.Configure<TablenameConfig>(configSection);
                _config = configSection.Get<TablenameConfig>();
                SqlMapperExtensions.TableNameMapper = TableName;
                return services;
            }
    
            private static string TableName(Type type) => _config.TableNames[type.FullName].Replace("`", "");
            public static string TableName<T>() => TableName(typeof(T));
        }
    }
    

    地点:

    // TablenameConfig.cs
    using System.Collections.Generic;
    
    namespace Dapper.Contrib.Extensions.Tablename
    {
        internal class TablenameConfig
        {
            public IDictionary<string, string> TableNames { get; set; }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-04-02
      • 1970-01-01
      • 2010-10-25
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-04
      • 2011-04-10
      相关资源
      最近更新 更多