我有一个正在使用API的应用程序。这样,它会查询对象中的所有ID,然后必须每个ID一次查询每个项目。我在Parallel.For循环中执行此操作,并将每个项目数据添加到数据表的一行中。然后,我使用sqlbulkcopy将数据表发送到SQL Server表。
如果我不使用Parallel.For进行此操作,则效果很好。但是,对于Parallel.For,此行:
workrow["id"] = Guid.NewGuid();
正在生成重复的Guid。它经常这样做,并且导致数据无法加载到SQL Server表中,因为SQL中的id行是主键,并且不允许重复。我尝试锁定:
lock (lockobject)
{
workrow["id"] = Guid.NewGuid();
}
这没有帮助。我尝试不给该字段分配一个ID,以希望SQL能够生成它(它在该字段上确实有newid())。不能说不能插入空值。我似乎不能只是从数据表中删除id字段,因为那样当我执行sqlbulkcopy时,列将无法对齐。
有人可以在这里帮助我吗?我要么需要弄清楚如何使Guid.NewGuid()停止产生重复项,要么我需要找出一种不传递id的方式(始终是数据表中的第一个字段),以便SQL生成id。 >
这是我用来生成表之一的代码:
public static DataTable MakeWorkflowTable() { DataTable Workflow = new DataTable("Workflow"); DataColumn id = new DataColumn("id", System.Type.GetType("System.Guid")); Workflow.Columns.Add(id); DataColumn OrgInfoID = new DataColumn("OrgInfoID", System.Type.GetType("System.Guid")); Workflow.Columns.Add(OrgInfoID); DataColumn Name = new DataColumn("Name", System.Type.GetType("System.String")); Workflow.Columns.Add(Name); DataColumn Active = new DataColumn("Active", System.Type.GetType("System.String")); Workflow.Columns.Add(Active); DataColumn Description = new DataColumn("Description", System.Type.GetType("System.String")); Workflow.Columns.Add(Description); DataColumn Object = new DataColumn("Object", System.Type.GetType("System.String")); Workflow.Columns.Add(Object); DataColumn Formula = new DataColumn("Formula", System.Type.GetType("System.String")); Workflow.Columns.Add(Formula); DataColumn ManageableState = new DataColumn("ManageableState", System.Type.GetType("System.String")); Workflow.Columns.Add(ManageableState); DataColumn NameSpacePrefix = new DataColumn("NameSpacePrefix", System.Type.GetType("System.String")); Workflow.Columns.Add(NameSpacePrefix); DataColumn TDACount = new DataColumn("TDACount", System.Type.GetType("System.Int32")); Workflow.Columns.Add(TDACount); DataColumn TriggerType = new DataColumn("TriggerType", System.Type.GetType("System.String")); Workflow.Columns.Add(TriggerType); DataColumn CreatedDate = new DataColumn("CreatedDate", System.Type.GetType("System.DateTime")); Workflow.Columns.Add(CreatedDate); DataColumn CreatedBy = new DataColumn("CreatedBy", System.Type.GetType("System.String")); Workflow.Columns.Add(CreatedBy); DataColumn LastModifiedDate = new DataColumn("LastModifiedDate", System.Type.GetType("System.DateTime")); Workflow.Columns.Add(LastModifiedDate); DataColumn LastModifiedBy = new DataColumn("LastModifiedBy", System.Type.GetType("System.String")); Workflow.Columns.Add(LastModifiedBy); return Workflow; }
这是我用来将其发送到SQL Server的代码:
public static void SendDTtoDB(ref DataTable dt, ref SqlConnection cnn, string TableName) { using (SqlBulkCopy bulkCopy = new SqlBulkCopy(cnn)) { bulkCopy.DestinationTableName = TableName; try { bulkCopy.WriteToServer(dt); dt.Clear(); } catch (Exception e) { logger.Warn("SendDTtoDB {TableName}: ORGID: {ORGID} : {Message}", TableName, dt.Rows[0]["OrgInfoID"], e.Message.ToString()); if (e.Message.ToString().Contains("PRIMARY KEY")) { foreach(DataRow row in dt.Rows) { logger.Warn("ID: {id}", row["id"]); } } } } }
您可以在catch语句中看到,我将其设置为在日志中写出ID,这样我就可以自己查看它们了,当然,那里有一个重复项。太令人沮丧了!我真的不想取出Parallel.For,如果不需要的话可以单线程处理。
每个请求,这是Parallel.For的代码
if (qr.totalSize > 0)
{
object lockobject = new object();
Parallel.For(0, qr.records.Length, i =>
{
ToolingService.CustomTab1 vr = new ToolingService.CustomTab1();
vr = (ToolingService.CustomTab1)qr.records[i];
string mdSOQL = "Select FullName, description, ManageableState, MasterLabel, NamespacePrefix, Type, Url, CreatedDate, CreatedBy.Name, "
+ "LastModifiedDate, LastModifiedBy.Name From CustomTab where id='" + vr.Id + "'";
ToolingService.QueryResult mdqr = new ToolingService.QueryResult();
ToolingService.CustomTab1 vrmd = new ToolingService.CustomTab1();
mdqr = ts.query(mdSOQL);
vrmd = (ToolingService.CustomTab1)mdqr.records[0];
DataRow workrow = CustomTabs.NewRow();
lock (lockobject)
{
workrow["id"] = Guid.NewGuid();
}
workrow["OrgInfoID"] = _orgDBID;
workrow["FullName"] = vrmd.FullName;
workrow["Description"] = vrmd.Description ?? Convert.DBNull;
workrow["ManageableState"] = vrmd.ManageableState;
workrow["MasterLabel"] = vrmd.MasterLabel ?? Convert.DBNull;
workrow["NameSpacePrefix"] = vrmd.NamespacePrefix ?? Convert.DBNull;
workrow["Type"] = vrmd.Type ?? Convert.DBNull;
workrow["URL"] = vrmd.Url ?? Convert.DBNull;
workrow["CreatedDate"] = vrmd.CreatedDate ?? Convert.DBNull;
if (vrmd.CreatedBy == null)
{
workrow["CreatedBy"] = Convert.DBNull;
}
else
{
workrow["CreatedBy"] = vrmd.CreatedBy.Name;
}
workrow["LastModifiedDate"] = vrmd.LastModifiedDate ?? Convert.DBNull;
if (vrmd.LastModifiedBy == null)
{
workrow["LastModifiedBy"] = Convert.DBNull;
}
else
{
workrow["LastModifiedBy"] = vrmd.LastModifiedBy.Name;
}
lock (CustomTabs)
{
CustomTabs.Rows.Add(workrow);
}
});
OrgTables.SendDTtoDB(ref CustomTabs, ref _cnn, "OrgCustomTabs");
我有一个正在使用API的应用程序。这样,它会查询对象中的所有ID,然后必须每个ID一次查询每个项目。我在Parallel.For循环中执行此操作,并且...
我以前见过这个问题。 Guid.NewGuid()
没问题,但是DataTable
不是线程安全的!