将app.config设置移动到db并使用值类型动态设置返回数据类型

时间:2016-10-03 21:27:17

标签: c# .net dapper

我有一个Windows服务应用程序,我想管理来自asp.net网站的设置。随着我的应用程序的增长,app.config文件中的设置列表也增长了。所以,我决定将这些设置移动到我的SQLDB中的一个表中,以便能够跟踪它们,并为我提供一种从管理站点修改设置的方法。我遇到了一个问题,我试图在表中存储设置值类型,然后使用它将value属性更改为存储的类型。例如,我定义了很多TimeSpan。在SQL表中,数据看起来像这样。

guid    settingName     settingValue    settingType
936767f5-63b5-4844-9991-29f6f92c53f2    SMTimeStart    12:00:00    TimeSpan

我尝试使用以下代码拉取设置并以正确的类型返回。

    public class SettingDataValue
    {
        public Guid guid { get; set; }
        public string SettingName { get; set; }
        public string SettingValue { get; set; }
        public string SettingType { get; set; }


    }
    public static dynamic getSettingFromDB(string name)
    {
        SettingDataValue s = new SettingDataValue();
        using (IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString), commandTimeout = null)
        {
            s = _db.Query<SettingDataValue>("Select Guid, SettingName, SettingValue ,SettingType from SiteSettings where settingName = '" + name + "'").SingleOrDefault();
        }
        PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);
        propertyInfo.SetValue(s, Convert.ChangeType(s.SettingValue, propertyInfo.PropertyType), null);

        return s.SettingValue;
    }

但是当我运行它时,我在

上得到一个空引用异常
propertyInfo.SetValue(s, Convert.ChangeType(s.SettingValue, propertyInfo.PropertyType), null);

我知道当我测试它并使用sql profiler观察时查询有效。有什么想法或建议吗?

2 个答案:

答案 0 :(得分:1)

所以我错了几件事。正如大卫所说,我不需要使用反射来获得类型。相反,我需要使用Type.GetType方法来解析文本。第二件事是数据类型必须是用它们记录的命名空间。

这是现在正在运行的更新代码。

    public class SettingDataValue
    {
        public Guid guid { get; set; }
        public string SettingName { get; set; }
        public string SettingValue { get; set; }
        public string SettingType { get; set; }

    }
    public static dynamic getSettingFromDB(string name)
    {

        SettingDataValue s = new SettingDataValue();
        using (IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["NetworkCafeConnectionString"].ConnectionString))
        {
            s = _db.Query<SettingDataValue>("Select guid, SettingName, SettingValue ,SettingType from SiteSettings where SettingName = '" + name + "'").FirstOrDefault();
        }
        Type type = Type.GetType(s.SettingType);
        var converter = TypeDescriptor.GetConverter(type);
        return converter.ConvertFrom(s.SettingValue);
    }

以下是sql表中的数据示例。

guid        SettingName            SettingValue    SettingType
95473a84    SMCreateTime           00:12:00        System.TimeSpan
81037bdc    SMCreateEnabled        True            System.Boolean
99e06df7    SMUsername             Username        System.String

答案 1 :(得分:0)

您遇到的问题不是您没有收到数据,而是PropertyInfo为空。

该行:

PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);

实际上是尝试在SettingDataValue对象上找到属性“TimeSpan”(使用您提供的数据行)。由于此属性不存在,因此返回null。然后,您尝试设置属性的值并获取空引用异常。

我认为你要做的是将字符串值转换为设置类型中的值类型。你不需要使用反射。我建议在您的SettingDataValue对象中添加只读属性:

public object Value
{
    get
    {
        return SomeMethodThatConvertsYourStringValueToTarget();
    }
}

然后是实际进行转换的私有方法。

private object SomeMethodThatConvertsYourStringValueToTarget();
{
    switch (SettingType)
    {
        case "TimeSpan":
            //conversion code
            break;
    }
}

然后更改getSettingsFromDb方法以返回对象而不是动态。然后你就可以使用它:

TimeSpan ts =(TimeSpan)getSettingsFromDb(“SMTimeStart”);

或者,您可以为每种数据类型创建一个方法,这样您在使用它时就不必考虑它。所以你可以使用它:

TimeSpan ts = getTimeStampFromDb(“SMTimeStart”);