我正在编写一个Web应用程序,它必须将多个Microsoft Access数据库(由旧的Windows可执行文件使用)转换为一个MySQL数据库(由该程序的新在线版本使用)。在这个过程中,我正在转换具有int作为主键(PK,而不是自动增量)和文本字段(TX,而不是唯一)的表,因此每个PK具有一个特定的TX但是一个TX可以具有许多PK值(don不问。这些表的很大一部分在所有Access数据库中都是相同的。
多个用户应该能够同时转换多个数据库。 我做了以下事情:
private static Mutex mx = new Mutex();
protected void ConvertTable()
{
// mx.WaitOne();
var db = new dbXYZ();
try
{
// Select old records from DataSet that holds all MS Access tables
var source = from [...] select a;
foreach (...)
{
// mx.WaitOne();
// Search oldTX in new MySQL table
var rec = (from [...] where TX=oldTX orderby PK select b).FirstOrDefault();
if (rec == null)
{
rec = new XYZ();
rec.TX = oldTX;
// Search oldPK in new MySQL table
var pk = (from [...] where PK=oldPK select c).FirstOrDefault();
if (pk != null)
rec.PK = GenerateNewPK();
else
rec.PK = oldPK;
// Add record and update MySQL immediately
db.XYZ.Add(rec);
db.SaveChanges();
}
// Temporarily remember relation old/new PK for further processing
pkTable[oldPK] = rec.PK;
// mx.Release();
}
}
catch
{
...
}
// mx.Release();
}
上述函数由转换类封装,当用户单击上载的MS Access数据库的链接时调用该转换类:
Task t = Task.Factory.StartNew(() =>
{
ConvClass conv = new ConvClass(DatabaseID, UploadPath);
}, TaskCreationOptions.LongRunning);
我添加了LongRunning
选项,因为我理解在这种情况下,每个StartNew
调用都会使用一个完整的单独线程。一个Access数据库的完整转换大约需要10-15分钟。
当同一个用户转换多个数据库并且我没有启用任何互斥锁调用时,会出现重复的PK错误。正如所料。
当同一个用户正在转换多个数据库并且我取消注释OUTER互斥锁调用时,并发转换在进入此函数时会相互等待。一切顺利,没有重复的PK错误。正如预期的那样。
但是当同一个用户正在转换多个数据库并且我取消注释INNER互斥锁调用时,我再次看到重复的PK错误。让用户逐个转换数据库(使用外部互斥锁调用)并不是那么糟糕但我想知道为什么这不起作用。
有谁可以告诉我为什么后者不起作用?
并且,当有多个用户(正在转换多个数据库)时,是否还需要考虑其他因素?