我正在开发一个具有peek性能要求的项目,因此我们需要批量(批量处理)多个操作(例如将数据持久保存到数据库中)以提高效率。
但是,我希望我们的代码能够保持易于理解的流程,例如:
input = Read();
parsed = Parse(input);
if (parsed.Count > 10)
{
status = Persist(parsed);
ReportSuccess(status);
return;
}
ReportFailure();
我在这里寻找的功能是自动使用Persks()以批量(并且异步)发生,但是对其用户表现得好像它是同步的(用户应该阻塞直到批量操作完成)。我希望实现者能够实现Persist(ICollection)。
我研究了基于流程的编程,我并不熟悉它。我在C#here中看到了一个用于fbp的库,并且与微软的Workflow Foundation有点玩,但我的印象是两者都对我需要的东西有点过分。您将使用什么来实现批量流行为?
请注意,我希望获得与我编写的代码完全相同的代码(简单易懂和调试),因此涉及到产量或配置以便将流相互连接的解决方案不适合我的目的。另外,chaining 不是我想要的 - 我不想先建立一个链然后运行它,我希望代码看起来好像是一个简单的流程(“做A,做B,如果C然后做D” )。
答案 0 :(得分:1)
常见问题 - 而不是调用Persist我通常将命令(或沿着这些行的smt)加载到Persistor类中,然后在循环结束后我调用Persistor.Persist来持久化批处理。
只需几点 - 如果您正在生成sql,那么您添加到persistor的命令可能会以某种方式表示您的查询(使用内置对象,自定义对象或仅查询字符串)。如果您正在调用存储过程,则可以使用命令将内容附加到一段xml,当您调用persist方法时,该内容将传递给SP。
希望它有所帮助 - 非常确定这有一种模式,但不知道这个名字:)
答案 1 :(得分:0)
答案 2 :(得分:0)
您可以做的一件简单事情是创建一个MemoryBuffer,您可以在其中推送消息,只需将它们添加到列表中并返回即可。这个MemoryBuffer有一个System.Timers.Timer,它会定期调用并进行“实际”更新。
可以在http://www.fantail.net.nz/wordpress/?p=5的Syslog服务器(C#)中找到一个这样的实现,其中系统日志消息会定期批量记录到SQL Server。
如果将数据推送到数据库很重要,这种方法可能不太好,就好像出现问题一样,你将丢失MemoryBuffer中的消息。
答案 3 :(得分:0)
如何使用BackgroundWorker
类在单独的线程上异步保存每个项目?例如:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
class PersistenceManager
{
public void Persist(ICollection persistable)
{
// initialize a list of background workers
var backgroundWorkers = new List<BackgroundWorker>();
// launch each persistable item in a background worker on a separate thread
foreach (var persistableItem in persistable)
{
var worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
backgroundWorkers.Add(worker);
worker.RunWorkerAsync(persistableItem);
}
// wait for all the workers to finish
while (true)
{
// sleep a little bit to give the workers a chance to finish
Thread.Sleep(100);
// continue looping until all workers are done processing
if (backgroundWorkers.Exists(w => w.IsBusy)) continue;
break;
}
// dispose all the workers
foreach (var w in backgroundWorkers) w.Dispose();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
var persistableItem = e.Argument;
// TODO: add logic here to save the persistableItem to the database
}
}