.net 结合推拉的数据访问模式?
我需要一些关于我应该使用什么样的模式将数据推/拉入我的应用程序的建议 我正在编写一个规则引擎,它需要在内存中保存相当多的数据才能足够有效。我有一些相互矛盾的要求.net 结合推拉的数据访问模式?,.net,design-patterns,data-access-layer,.net,Design Patterns,Data Access Layer,我需要一些关于我应该使用什么样的模式将数据推/拉入我的应用程序的建议 我正在编写一个规则引擎,它需要在内存中保存相当多的数据才能足够有效。我有一些相互矛盾的要求 发动机始终必须等待所有数据完全预加载后才能正常工作,这是不可接受的 只有按需获取和缓存数据才会导致引擎在运行速度足够快之前花费太长时间 外部事件可以触发重新加载数据特定部分的需要 基本上,我认为我需要将数据推拉到应用程序中 我当前“模式”的简化版本如下所示(在用记事本编写的psuedo-C中): //此接口由所有需要数据的类实现 接口I
//此接口由所有需要数据的类实现
接口IDataSubscriber
{
无效注册数据(实体数据);
}
//此接口由数据访问类实现
接口IDataProvider
{
重新加载无效(密钥数据密钥);
无效登记认购人(IDataSubscriber认购人);
}
需要数据的类MyClass:IDataSubscriber
{
IDataProvider_供应商;
需要数据的MyClasses(IDataProvider提供程序)
{
_提供者=提供者;
_提供者、注册者、认购者(本);
}
公共无效注册表数据(实体数据)
{
//保存数据以备将来使用
StoreDataInCache(数据);
}
无效使用数据(键)
{
//确保数据已存储在缓存中
_提供者。重新加载(密钥);
实体数据=GetDataFromCache(键);
}
}
类MyDataProvider:IDataProvider
{
列出订户名单;
//确保密钥的数据已加载到所有订阅者
重新加载公共无效(密钥)
{
如果(已标记钥匙(钥匙))
返回;
PublishDataToSubscribers(关键);
markkeyasload(key);
}
//强制所有订阅服务器为密钥获取新版本的数据
公共无效强制重新加载(密钥)
{
PublishDataToSubscribers(关键);
markkeyasload(key);
}
作废PublishDataToSubscribers(键)
{
实体数据=FetchDataFromStore(键);
foreach(var用户在_用户中)
{
用户注册数据(数据);
}
}
}
//此类将在启动时分离,并应确保所有数据
//尽快预加载
类MyPreload线程
{
IDataProvider_供应商;
MyPreload线程(IDataProvider提供程序)
{
_提供者=提供者;
}
void RunInBackground()
{
IEnumerable allKeys=GetAllKeys();
foreach(所有键中的var键)
{
_提供者。重新加载(密钥);
}
}
}
我觉得这不一定是最好的方法。。解释它似乎需要两页纸,这似乎是一种暗示
有什么想法吗?有什么模式我应该看一下吗?你可以从一些简单的东西开始,比如基于的解决方案。然后,您可以尝试通过增加现金来提高性能。您可以从一些简单的事情开始,比如基于现金的解决方案。然后,您可以尝试通过增加现金来提高绩效。毫无疑问,应该是这样的
- 并发模式之一(例如)
- 生产者-消费者模式(队列)
- 延迟加载(按需数据)
- 延迟卸载模式
- 策略模式(用于实现数据访问算法)
- 多线程访问保护 资源(缓存)
我的投票-使用共享队列(总线)+惰性模式+缓存,毫无疑问,应该是
- 并发模式之一(例如)
- 生产者-消费者模式(队列)
- 延迟加载(按需数据)
- 延迟卸载模式
- 策略模式(用于实现数据访问算法)
- 多线程访问保护 资源(缓存)
我的投票-关于网关模式的共享队列(总线)+惰性模式+缓存,我不得不同意Fowler(引用你给出的链接)“答案非常普遍,几乎不值得一提。”。正如我在问题中所说的,仅仅按需缓存不会起到作用,因为这会使引擎太慢太长时间。问题“我有大量数据。如何快速处理它?”非常普遍,几乎不值得期待详细的答案。关于网关模式,我必须同意Fowler(引用您提供的链接)“答案非常普遍,几乎不值得一提。”。正如我在问题中所说的,仅仅按需缓存不会起作用,因为这会使引擎太慢太长时间。问题是“我有大量数据。”。如何快速处理它?“非常普遍,很难期望得到详细的答案。有趣的是,我喜欢活动对象模式处理并发的方式。我也是。我认为,这对于很多任务来说都是很好的:调试多线程应用程序是一项困难的工作,而且有许多应用程序不支持并发访问。所以AO是一种很好的方式,可以添加对共享资源的受控访问,并通过使用优先级来管理任务。有趣的是,我喜欢活动对象模式处理并发性的方式。我也是。我认为,这对于很多任务来说都是非常好的:调试多线程应用程序是一项困难的工作,并且有许多应用程序不支持并发访问。因此,AO是一种很好的方式,可以添加对共享资源的受控访问,并通过使用优先级来管理任务。
// This interface is implemented by all classes that needs the data
interface IDataSubscriber
{
void RegisterData(Entity data);
}
// This interface is implemented by the data access class
interface IDataProvider
{
void EnsureLoaded(Key dataKey);
void RegisterSubscriber(IDataSubscriber subscriber);
}
class MyClassThatNeedsData : IDataSubscriber
{
IDataProvider _provider;
MyClassThatNeedsData(IDataProvider provider)
{
_provider = provider;
_provider.RegisterSubscriber(this);
}
public void RegisterData(Entity data)
{
// Save data for later
StoreDataInCache(data);
}
void UseData(Key key)
{
// Make sure that the data has been stored in cache
_provider.EnsureLoaded(key);
Entity data = GetDataFromCache(key);
}
}
class MyDataProvider : IDataProvider
{
List<IDataSubscriber> _subscribers;
// Make sure that the data for key has been loaded to all subscribers
public void EnsureLoaded(Key key)
{
if (HasKeyBeenMarkedAsLoaded(key))
return;
PublishDataToSubscribers(key);
MarkKeyAsLoaded(key);
}
// Force all subscribers to get a new version of the data for key
public void ForceReload(Key key)
{
PublishDataToSubscribers(key);
MarkKeyAsLoaded(key);
}
void PublishDataToSubscribers(Key key)
{
Entity data = FetchDataFromStore(key);
foreach(var subscriber in _subscribers)
{
subscriber.RegisterData(data);
}
}
}
// This class will be spun off on startup and should make sure that all data is
// preloaded as quickly as possible
class MyPreloadingThread
{
IDataProvider _provider;
MyPreloadingThread(IDataProvider provider)
{
_provider = provider;
}
void RunInBackground()
{
IEnumerable<Key> allKeys = GetAllKeys();
foreach(var key in allKeys)
{
_provider.EnsureLoaded(key);
}
}
}