我有,我必须一般来说检查整个基地做东西控制台应用程序...倍数连接到Oracle - 多任务
要做到这一点,我使用Tasks
这样的:
static void Main(string[] args)
{
var dateStart = DateTime.Now.AddDays(-35);
var dateEnd = DateTime.Now;
var taskList = new List<Task>();
while (dateStart > dateEnd ? dateStart >= dateEnd : dateStart <= dateEnd)
{
var d = dateStart.Date;
var dispositivesBll = new DispositivesBll();
taskList.Add(Task.Run(() =>
{
dispositivesBll.Foo(d);
}).ContinueWith(
x => dispositivesBll.Dispose())
.ContinueWith(x => GC.Collect()));
var dispositivesBllNew = new DispositivesBll();
taskList.Add(Task.Run(() =>
{
dispositivesBllNew.Boo(d);
}).ContinueWith(
x =>
dispositivesBllNew.Dispose())
.ContinueWith(x => GC.Collect()));
if (taskList.Count >= 2 * 5)
{
Task.WaitAll(taskList.ToArray());
taskList.Clear();
}
dateStart = dateStart > dateEnd ? dateStart.AddDays(-1) : dateStart.AddDays(1);
}
Task.WaitAll(taskList.ToArray());
所以基本上我想要运行10天一次在if (taskList.Count >= 2 * 5)
你可能注意到了,但问题是,我Foo
和Boo
方法有多个连接到一个Oracle数据库。
public class DispositivesBll : IDisposable
{
private readonly OracleDal _oracleDal = new OracleDal();
public void Foo(DateTime data)
{
var t1 = Task.Run(() =>
{
_listSuccess = _oracleDal.GetSuccessList();
});
var t2 =
Task.Run(() =>
{
listFailure = _oracleDal.GetFailureList();
});
t1.Wait();
t2.Wait();
foreach (var success in _listSuccess)
{
//Some logic to insert objects into a "mergeList"
}
if (mergeList.Any())
Task.Run(() => _oracleDal.MergeList(mergeList)).Wait();
}
public void Dispose()
{
if (_hash != null)
_hash.Clear();
_hash = null;
}
}
和我的合并方法:
public void MergeList(List<MyObject> mergeList)
{
using (var conn = new OracleConnection(Connection.ConnectionString))
{
if (conn.State != ConnectionState.Open)
conn.Open();
using (var oCommand = conn.CreateCommand())
{
oCommand.CommandType = CommandType.Text;
oCommand.CommandText = string.Format(@"
MERGE INTO MyTable dgn
USING (select id from another_table where field = :xpe) d ON (TO_CHAR(dateHappen, 'DDMMYYYY') = {0} and id = :xId) WHEN MATCHED THEN
UPDATE SET OK = :xOk, dateHappen = SYSDATE
WHEN NOT MATCHED THEN
INSERT (fields....)
VALUES (values...)");
oCommand.BindByName = true;
oCommand.ArrayBindCount = mergeList.Count;
oCommand.Parameters.Add(":xId", OracleDbType.Int32,
mergeList.Select(c => Convert.ToInt32(c.Id)).ToArray(), ParameterDirection.Input);
oCommand.Parameters.Add(":xPe", OracleDbType.Varchar2,
mergeList.Select(c => Convert.ToString(c.Xpe)).ToArray(), ParameterDirection.Input);
oCommand.ExecuteNonQuery();
}
}
}
的问题是:对于每一个“天”,它tooks约2小时来处理一切......我们有一个计划,每天备份我们的数据库造成该数据库停止大约10分钟...所以它会导致我的过程中锁...
那么我该怎么做?我手动停止这个过程,并再次启动它,避免已经执行的日期。但是如果我打开了20个连接,他们会保持这种方式......所以我必须每次都杀掉这些会话......有没有办法强制所有连接处置?
编辑:
MyTable
有50英里行....由ID | STATE | DATE
组成......基本上我必须要跨越这些国家与他们的日期...... 因此,最大的延迟它的数据库。 ..它还挺一个已知的问题,我们要重构整个数据库模型....我们要尽快做到这一点...
但不管怎么说,尽管处理时间,如果我可以管理(或强制)连接杀死,它会很好...
任何想法?
'每天两小时'处理时间的大部分发生在哪里?它在数据库端还是应用端?如果你用更小的批次更频繁地运行它,这可能会更好吗?这可能不是一个简单修复的情况;在分析整个过程之后可能需要重新设计。 – gmiley
“日”合并过程不应该花费2个小时左右的时间来运行;即使在数百万行的数据库表上,它也应该在几分钟或更短的时间内运行。你能给我们一个粗略的想法:表'MyTable'中有多少行,'another_table'中有多少行 - 并且你的设计被设置为手动关闭和重启进程也是令人担忧的。另外,您的数据库应该使用适当的RMAN备份进入归档日志模式,因此您不必每天都进行数据库导出。 –
大部分是在数据库端,当然..有一个相同的实现(没有任务),每天花费4个小时..而我设法在2个小时内完成......但我真的需要一些东西来控制所有连接....我用一些信息编辑了这个问题....“MyTable”和“another_table”每行有超过50英里的行......所以它很大。我必须将每条记录与其他大表连接起来......有时,连接会发生VARCHAR2(15)值...所以它的模型非常糟糕...... –