0

我正在开发一个需要在数据库中存储和更新配置的网络应用程序。例如,我可能会存储用户偏好,如默认颜色、语言、首选日期格式等。

数据库表由名称/值对 (nvarchars) 组成。很简单。

我正在使用 ORM 来获取这些名称/值字符串对的列表(实际上是 IEnumerable)。我的问题是我需要将这些 IEnumerable 转换为比名称/值字符串更具表现力的东西。也就是说,我想做一个强类型的配置对象。

理想情况下,我想让这个配置对象不直接依赖于 ORM,但我不确定如何去做,因为这个对象的初始化和用户偏好的持久性需要通过ORM。

某种设计模式来拯救?

(没关系,但我使用的是 C# 和实体框架。)


编辑:

假设我的域对象中有以下字段:

public class SettingNameValuePair {
    public string Name {get;set;}
    public string Value {get;set;}
}

public class GlobalSettings {
    public System.Drawing.Color FontColor {get;set;}
    public TimeZoneInfo DefaultTimeZone {get;set;}
    public DateTime DateCreated {get;set;}

    ... constructor ...
    ... validation, other functions ...
}

我可以毫不费力地设置我的 ORM 来获取和持久化 SettingNameValuePair。但是,我如何获取和持久化 GlobalSettings?也就是说,在我的应用程序的某个地方,我想获得一个全局设置的实例。

using (var context = new ApplicationContext()) {    
    GlobalSettings settings = ???
}

当然,ORM 不知道如何在 SettingNameValuePair 和 GlobalSettings 之间自动转换。我知道我需要编写一些“管道”代码来生成 GlobalSettings 的强类型属性。

我的问题是:什么是取回由 SettingNameValuePair 填充的 GlobalSettings 实例的好方法?这里有两个选项肯定是错误的:

1) 让 GlobalSettings 的构造函数将数据上下文作为参数。这引入了不良的依赖性并且难以测试。

2) 让 GlobalSettings 的构造函数从数据上下文中获取 SettingNameValuePair,如下所示:

using (var context = new ApplicationContext()) {    
    IEnumerable<SettingNameValuePair> nameValuePairs = 
        context.NameValuePairs.ToList();
    GlobalSettings settings = new GlobalSettings(nameValuePairs);
}

这样做的问题是您必须在所有地方重复此代码。

我觉得有更好的解决方案涉及单例、静态类、代理或工厂方法,但我对这些概念还不满意。

4

2 回答 2

1

不要在您的域对象中引用您的 ORM,而是在存储库中实现它,这将利用您的 ORM 或任何数据访问技术(例如数据读取器,因为大多数 orms 将无法在键值对和强类型对象之间进行映射)。

我也不建议在构造函数中给实体(全局设置)一个键值对,因为它与域无关,将键值对映射到域对象,而是在映射器层中实现映射,这是您的存储库或 dal

例如:

在应用层

public GlobalSettings GetUserSettings(User user)
{
  return _globalSettingsRepository.GetGlobalSettings(user);
}

在存储库层

public GlobalSettings GetGlobalSettings(User user)
{
  var keyvalue = _context.blablabla();
  var globalSettings = new GlobalSettings { Id = keyvalue["key"], DateCreated = DateTime.Parse(keyvalue["datecreated"]) };
  return globalSettings
}
于 2011-10-04T16:11:15.207 回答
0

我认为没有任何 ORM 可以映射到键值对。事实上,对这些数据使用 DataReader 可能会更有效。无论您如何获取数据,您都可以简单地使用配置 KVP 来构建字典,然后使用属性模式进行访问。然后,您可以为您知道需要的属性创建强类型访问器。这将允许您将强类型对象用于您知道的属性,同时仍然保持在不更改代码的情况下添加属性的灵活性。

于 2011-10-04T15:41:58.437 回答