存储 Web 应用程序设置和选项的最佳方式
Best way for store a web application settings and options
我正在开发一个 ASP.Net MVC 5 网络应用程序,它是一个博客并有一个管理员区域。管理区有一些功能,比如用户可以在 post 上发表评论等等......但也许管理员改变了主意,他只想允许注册用户发表评论。我的意思是选项是动态的。
问题是这些选项的数据存储在哪里是最好的?
由于频繁查询,我避免为这些数据创建 table!
我的第二个想法是同时使用数据库和缓存,但我正在寻找实现它的最佳方法...
有更好的办法吗?
使用数据库表来存储数据,如果数据量不是很大,当用户登录时,一次检索数据并存储在用户会话对象中,以便快速访问。
我在我维护的 Web 应用程序中做同样的事情。除非您有大量(如数千或数百万)不同的设置或一个非常慢的数据库,否则将设置保存在数据库中并在每次需要时检索您需要的特定设置应该没问题。如果您担心数据库性能,您可以在用户登录时检查一次并将它们保存为会话(如果它们是特定于用户的)或应用程序变量。但是,用户不会立即看到更改,只有在下次登录后才会看到。
就个人而言,我会先选择纯数据库选项并进行测试。如果它的表现不够好,切换到 session/application 变量选项将是微不足道的。
将您的主要存储保留为您的数据库,但从缓存中处理请求。对于缓存回收的情况(可能在内存中甚至 external/distributed 缓存中)
,您的数据库将始终是实际存储
缓存应用程序启动时或首次访问管理操作时经常更改的设置。
为缓存中的所有后续操作提供服务to/from。对设置的任何更改,更新到缓存和从缓存更新。
运行 job/service 同步缓存和数据库,大约每小时一次。
优点:
- 访问速度很快,因为它来自缓存。
- 更新很快,因为它是缓存。
- 数据库访问非常少且可预测。
缺点:
- 数据库最多会延迟一个小时左右。
- 在缓存回收的情况下,您将拥有一个小时前的陈旧数据,但绝不会完全丢失。
将其存储在数据库中。那部分很简单。如果您担心查询数据库的次数过多,则可以将查询结果缓存一段时间。在最简单的情况下,它看起来像:
ObjectCache cache = MemoryCache.Default;
var key = "MyAwesomeSettings";
var settings = cache.Get(key);
if (settings == null)
{
settings = // query settings;
cache.Add(key, settings, DateTimeOffset.UtcNow.AddHours(1));
}
但是,MemoryCache
的一个关键问题是它受进程限制。如果您使用的是 Web Worker,那么每个 Worker 都有一个唯一的缓存,因为每个 Worker 都是一个单独的进程。不过,您可以使用像 Redis 这样的 NoSQL 解决方案来创建分布式缓存,该缓存可以在工作人员之间共享并且启动时更有弹性。
我使用这种方法..它使用 json 文件。 json 文件对于任何类型的值都非常灵活,并且可以在文件更改时刷新而无需重新启动应用程序..
正在定义配置部分..
namespace ConfigTest.Configuration
{
public class MyConfig:ConfigurationSection
{
私有静态 JObject _props;
私有静态 FileSystemWatcher 观察者;
[ConfigurationProperty("path", IsRequired = true)]
public string Path
{
get { return (string)this["path"]; }
set { this["path"] = value; }
}
[ConfigurationProperty("watch", IsRequired = false)]
public bool Watch
{
get { return (bool)this["watch"]; }
set { this["watch"] = value; }
}
private static JObject GetValues(string path)
{
string data = File.ReadAllText(path);
JObject j = JObject.Parse(data);
return j;
}
public static T Read<T>(string path)
{
var token = _props.SelectToken(path);
if (token == null)
return default(T);
return token.ToObject<T>();
}
public static void Load()
{
MyConfig section = (MyConfig)ConfigurationManager.GetSection("myConfig");
string path = section.Path;
LoadValues(path);
if (section.Watch)
FileSystemWatcher(path);
}
private static void LoadValues(string path)
{
JObject props = GetValues(path);
_props = props;
}
private static void FileSystemWatcher(string path)
{
if (watcher != null)
watcher.Dispose();
watcher = new System.IO.FileSystemWatcher();
watcher.Path = System.IO.Path.GetDirectoryName(path);
watcher.Filter = System.IO.Path.GetFileName(path);
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
FileSystemWatcher watcher = (FileSystemWatcher)sender;
watcher.EnableRaisingEvents = false;
LoadValues(e.FullPath);
watcher.EnableRaisingEvents = true;
}
}
}
部分定义
<configSections>
<!--important!! its should be your config type name space-->
<section name="myConfig" type="ConfigTest.Configuration.MyConfig, ConfigTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
设置文件路径和观看的配置属性
<!--important! locate it in App_Data or Outside the project directory-->
<myConfig watch="true" path="yourpath/myConfig.json" />
配置文件myConfig.json
{
"someIntProperty": 1,
"someStringProperty": "string",
"someObjectProperty":{
"id": 1,
"name": "parentObjectName",
"someChildeObject":{
"childObjectId": 1,
"childObjectName": "child object name "
}
}
}
如何使用..
你可以得到类型
的值
int intvalue = MyConfig.Read<int>("someIntProperty");
你可以获得定义的类型object
SomeClass objectValue = MyConfig.Read<SomeClass>("someObjectProperty");
public class SomeClass
{
public int Id { get; set; }
public string Name { get; set; }
public SomeClass2 SomeChildeObject { get; set; }
}
public class SomeClass2
{
public int ChildObjectId { get; set; }
public string ChildObjectName { get; set; }
}
或者你可以直接获取任何 child 与 属性 路径
string value = MyConfig.Read<string>("someObjectProperty.someChildeObject.childObjectName");
希望对您有所帮助
我正在开发一个 ASP.Net MVC 5 网络应用程序,它是一个博客并有一个管理员区域。管理区有一些功能,比如用户可以在 post 上发表评论等等......但也许管理员改变了主意,他只想允许注册用户发表评论。我的意思是选项是动态的。
问题是这些选项的数据存储在哪里是最好的?
由于频繁查询,我避免为这些数据创建 table!
我的第二个想法是同时使用数据库和缓存,但我正在寻找实现它的最佳方法...
有更好的办法吗?
使用数据库表来存储数据,如果数据量不是很大,当用户登录时,一次检索数据并存储在用户会话对象中,以便快速访问。
我在我维护的 Web 应用程序中做同样的事情。除非您有大量(如数千或数百万)不同的设置或一个非常慢的数据库,否则将设置保存在数据库中并在每次需要时检索您需要的特定设置应该没问题。如果您担心数据库性能,您可以在用户登录时检查一次并将它们保存为会话(如果它们是特定于用户的)或应用程序变量。但是,用户不会立即看到更改,只有在下次登录后才会看到。
就个人而言,我会先选择纯数据库选项并进行测试。如果它的表现不够好,切换到 session/application 变量选项将是微不足道的。
将您的主要存储保留为您的数据库,但从缓存中处理请求。对于缓存回收的情况(可能在内存中甚至 external/distributed 缓存中)
,您的数据库将始终是实际存储缓存应用程序启动时或首次访问管理操作时经常更改的设置。
为缓存中的所有后续操作提供服务to/from。对设置的任何更改,更新到缓存和从缓存更新。
运行 job/service 同步缓存和数据库,大约每小时一次。
优点:
- 访问速度很快,因为它来自缓存。
- 更新很快,因为它是缓存。
- 数据库访问非常少且可预测。
缺点:
- 数据库最多会延迟一个小时左右。
- 在缓存回收的情况下,您将拥有一个小时前的陈旧数据,但绝不会完全丢失。
将其存储在数据库中。那部分很简单。如果您担心查询数据库的次数过多,则可以将查询结果缓存一段时间。在最简单的情况下,它看起来像:
ObjectCache cache = MemoryCache.Default;
var key = "MyAwesomeSettings";
var settings = cache.Get(key);
if (settings == null)
{
settings = // query settings;
cache.Add(key, settings, DateTimeOffset.UtcNow.AddHours(1));
}
但是,MemoryCache
的一个关键问题是它受进程限制。如果您使用的是 Web Worker,那么每个 Worker 都有一个唯一的缓存,因为每个 Worker 都是一个单独的进程。不过,您可以使用像 Redis 这样的 NoSQL 解决方案来创建分布式缓存,该缓存可以在工作人员之间共享并且启动时更有弹性。
我使用这种方法..它使用 json 文件。 json 文件对于任何类型的值都非常灵活,并且可以在文件更改时刷新而无需重新启动应用程序..
正在定义配置部分..
namespace ConfigTest.Configuration
{ public class MyConfig:ConfigurationSection { 私有静态 JObject _props; 私有静态 FileSystemWatcher 观察者;
[ConfigurationProperty("path", IsRequired = true)]
public string Path
{
get { return (string)this["path"]; }
set { this["path"] = value; }
}
[ConfigurationProperty("watch", IsRequired = false)]
public bool Watch
{
get { return (bool)this["watch"]; }
set { this["watch"] = value; }
}
private static JObject GetValues(string path)
{
string data = File.ReadAllText(path);
JObject j = JObject.Parse(data);
return j;
}
public static T Read<T>(string path)
{
var token = _props.SelectToken(path);
if (token == null)
return default(T);
return token.ToObject<T>();
}
public static void Load()
{
MyConfig section = (MyConfig)ConfigurationManager.GetSection("myConfig");
string path = section.Path;
LoadValues(path);
if (section.Watch)
FileSystemWatcher(path);
}
private static void LoadValues(string path)
{
JObject props = GetValues(path);
_props = props;
}
private static void FileSystemWatcher(string path)
{
if (watcher != null)
watcher.Dispose();
watcher = new System.IO.FileSystemWatcher();
watcher.Path = System.IO.Path.GetDirectoryName(path);
watcher.Filter = System.IO.Path.GetFileName(path);
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
FileSystemWatcher watcher = (FileSystemWatcher)sender;
watcher.EnableRaisingEvents = false;
LoadValues(e.FullPath);
watcher.EnableRaisingEvents = true;
}
}
}
部分定义
<configSections>
<!--important!! its should be your config type name space-->
<section name="myConfig" type="ConfigTest.Configuration.MyConfig, ConfigTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
设置文件路径和观看的配置属性
<!--important! locate it in App_Data or Outside the project directory-->
<myConfig watch="true" path="yourpath/myConfig.json" />
配置文件myConfig.json
{
"someIntProperty": 1, "someStringProperty": "string", "someObjectProperty":{ "id": 1, "name": "parentObjectName", "someChildeObject":{ "childObjectId": 1, "childObjectName": "child object name " } } }
如何使用..
你可以得到类型
的值 int intvalue = MyConfig.Read<int>("someIntProperty");
你可以获得定义的类型object
SomeClass objectValue = MyConfig.Read<SomeClass>("someObjectProperty");
public class SomeClass
{
public int Id { get; set; }
public string Name { get; set; }
public SomeClass2 SomeChildeObject { get; set; }
}
public class SomeClass2
{
public int ChildObjectId { get; set; }
public string ChildObjectName { get; set; }
}
或者你可以直接获取任何 child 与 属性 路径
string value = MyConfig.Read<string>("someObjectProperty.someChildeObject.childObjectName");
希望对您有所帮助