0
foreachループを使用してデータベースに5000レコードを挿入しようとしています。それは要件に応じて受け入れられない約10分を取っている。私はまた、最初にデータテーブルにレコードを挿入し、それをXMLに変換して挿入を行うストアドプロシージャに渡す方法について考えました。しかし残念ながら私の状況には合っていません。今私はparallel.foreachを使用して同じことをやっているが、10レコードを挿入した後、私は "プライマリキーのユニークな制約違反"エラーメッセージを取得しています。私は並列プログラミングに新しいので、解決策を得られません。私のコードは以下の通りです。parallel.foreachを使用してデータベースに複数のレコードを挿入
public ActionResult ChannelBulkUpload(HttpPostedFileBase excelFile)
{
bool flag = true;
string path = Server.MapPath("~/Content/UploadFolder/" + excelFile.FileName);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
excelFile.SaveAs(path);
DataTable dt = GetDataTableFromExcel(excelFile, true);
ParallelOptions options = new ParallelOptions
{
MaxDegreeOfParallelism = 4
};
Parallel.ForEach(dt.AsEnumerable(), row =>
{
flag = true;
decimal Key = 0;
string value = "";
decimal channelMstKey = 0;
decimal channelGrpMstKey = 0;
decimal srcFuncKey = 0;
string ExcelMasterChDisplayName = row["MASTER_CHANNEL_DISPLAY_NAME"].ToString();
string ExcelGenreValue = row["GENRE"].ToString();
string ExcelAdsharpValue = row["ADSHARP"].ToString();
string ExcelClusterValue = row["CLUSTER"].ToString();
string ExcelNetworkValue = row["NETWORK"].ToString();
string ExcelBroadCastValue = row["BROADCAST"].ToString();
string ExcelFunctionalAreaname = row["FUNCTIONAL_AREA"].ToString();
string[] Ch_Grp_types = { "GENRE", "ADSHARP", "CLUSTER", "NETWORK", "PLATFORM" };
BarcDataContext bc = new BarcDataContext();
srcFuncKey = bc.REF_SRC_FUNC_AREA.Where(m => m.SRC_FUNC_AREA == ExcelFunctionalAreaname).FirstOrDefault().SRC_FUNC_KEY;
for (int j = 0; j < Ch_Grp_types.Length && flag; j++)
{
if (Ch_Grp_types[j] == "GENRE")
{
Key = 1;
value = ExcelGenreValue;
}
else if (Ch_Grp_types[j] == "NETWORK")
{
Key = 2;
value = ExcelNetworkValue;
}
else if (Ch_Grp_types[j] == "ADSHARP")
{
Key = 3;
value = ExcelAdsharpValue;
}
else if (Ch_Grp_types[j] == "CLUSTER")
{
Key = 4;
value = ExcelClusterValue;
}
else if (Ch_Grp_types[j] == "PLATFORM")
{
Key = 5;
value = ExcelBroadCastValue;
}
DIM_CHANNEL_MST objChMst = bc.DIM_CHANNEL_MST.Where(m => m.CHANNEL_MST_NAME_UPPER == ExcelMasterChDisplayName.ToUpper().Trim()).FirstOrDefault();
if (objChMst == null)
{
flag = false;
}
else
{
if (!string.IsNullOrEmpty(value))
{
var query =
(from A in bc.XREF_CH_GRP_DET_TAG
join B in bc.XREF_CH_GRP_MST_TAG on A.CH_GRP_MST_KEY equals B.CH_GRP_MST_KEY
where A.IS_ACTIVE == "Y" && B.IS_ACTIVE == "Y" && B.CH_GRP_TYPE_KEY == Key && B.CH_GRP_MST_NAME_UPPER == value.ToUpper()
select new XrefChannelGrpDetailTagVM
{
channelGrpDetKey = A.CH_GRP_DET_KEY,
channelGrpMasterNameUpper = B.CH_GRP_MST_NAME_UPPER,
}).Distinct().ToList();
var query2 =
(from A in bc.XREF_CH_GRP_DET_TAG
join B in bc.XREF_CH_GRP_MST_TAG on A.CH_GRP_MST_KEY equals B.CH_GRP_MST_KEY
where A.CHANNEL_MST_KEY == objChMst.CHANNEL_MST_KEY && B.CH_GRP_TYPE_KEY == Key && B.SRC_FUNC_KEY == srcFuncKey
select new XrefChannelGrpDetailTagVM
{
sr_no = A.SR_NO,
channelMstKey = A.CHANNEL_MST_KEY,
channelGrpDetKey = A.CH_GRP_DET_KEY,
channelGrpMstKey = A.CH_GRP_MST_KEY,
srcFuncKey = B.SRC_FUNC_KEY,
channelGrpTypeKey = B.CH_GRP_TYPE_KEY
}).Distinct().ToList();
XREF_CH_GRP_MST_TAG objXrefChGrpMst = bc.XREF_CH_GRP_MST_TAG.Where(m => m.CH_GRP_TYPE_KEY == Key && m.SRC_FUNC_KEY == srcFuncKey && m.CH_GRP_MST_NAME_UPPER == value.ToUpper()).FirstOrDefault();
if (objXrefChGrpMst != null)
{
channelMstKey = objChMst.CHANNEL_MST_KEY;
channelGrpMstKey = objXrefChGrpMst.CH_GRP_MST_KEY;
XREF_CH_GRP_DET_TAG objGrpDetail = new XREF_CH_GRP_DET_TAG();
if (query.Count == 0)
{
objGrpDetail.CH_GRP_DET_KEY = Get_Max_Of_Ch_Grp_Det_Key();
}
else
{
foreach (var detKey in query)
{
if (detKey.channelGrpMasterNameUpper == value.ToUpper())
{
objGrpDetail.CH_GRP_DET_KEY = detKey.channelGrpDetKey;
}
else
{
objGrpDetail.CH_GRP_DET_KEY = Get_Max_Of_Ch_Grp_Det_Key();
}
}
}
if (query2.Count > 0)
{
foreach (var abc in query2)
{
if (abc.channelMstKey == objChMst.CHANNEL_MST_KEY && abc.srcFuncKey == srcFuncKey && abc.channelGrpTypeKey == Key)
{
if (abc.channelGrpDetKey == objGrpDetail.CH_GRP_DET_KEY && abc.channelGrpMstKey == objXrefChGrpMst.CH_GRP_MST_KEY)
{
//Reject
}
else
{
//Update
XREF_CH_GRP_DET_TAG obj = bc.XREF_CH_GRP_DET_TAG.Where(m => m.SR_NO == abc.sr_no).FirstOrDefault();
obj.CH_GRP_DET_KEY = objGrpDetail.CH_GRP_DET_KEY;
obj.CH_GRP_MST_KEY = objXrefChGrpMst.CH_GRP_MST_KEY;
objGrpDetail.CREATE_DATE = DateTime.Now;
objGrpDetail.LAST_UPD_DATE = DateTime.Now;
objGrpDetail.IS_ACTIVE = "Y";
bc.SaveChanges();
}
}
else
{
//Insert
objGrpDetail.CH_GRP_MST_KEY = channelGrpMstKey;
objGrpDetail.CHANNEL_MST_KEY = channelMstKey;
objGrpDetail.SR_NO = Get_Max_Of_XREF_CH_GRP_DET();
objGrpDetail.CREATE_DATE = DateTime.Now;
objGrpDetail.LAST_UPD_DATE = DateTime.Now;
objGrpDetail.IS_ACTIVE = "Y";
bc.XREF_CH_GRP_DET_TAG.Add(objGrpDetail);
bc.SaveChanges();
}
}
}
else
{
objGrpDetail.CH_GRP_MST_KEY = channelGrpMstKey;
objGrpDetail.CHANNEL_MST_KEY = channelMstKey;
objGrpDetail.SR_NO = Get_Max_Of_XREF_CH_GRP_DET();
objGrpDetail.CH_GRP_DET_KEY = objGrpDetail.CH_GRP_DET_KEY;
objGrpDetail.CREATE_DATE = DateTime.Now;
objGrpDetail.LAST_UPD_DATE = DateTime.Now;
objGrpDetail.IS_ACTIVE = "Y";
bc.XREF_CH_GRP_DET_TAG.Add(objGrpDetail);
bc.SaveChanges();
}
}
}
}
}
});
TempData["SuccessMsg"] = "Records uploaded Successfully";
return RedirectToAction("CreateChannel");
}
以下の関数を使用して主キー値を生成する際にエラーを取得する:
SR_NOはそのテーブルの主キーであるpublic static decimal Get_Max_Of_XREF_CH_GRP_DET()
{
try
{
BarcDataContext bc = new BarcDataContext();
return bc.XREF_CH_GRP_DET_TAG.Max(m => m.SR_NO) + 1;
}
catch (Exception e)
{
return 1;
}
}
。
ご協力いただければ幸いです。前もって感謝します。
並列ループ内のループデータベースに接続し、主キーの最大値のチェック:あなたのデータベースとしてSQL Serverを使用している場合は、関連するコードは次のようになります。 Parallelは非常に悪い考えです。少なくとも、IDを生成する部分をスレッドセーフにする必要があります。 – user3185569
parallel.foreachを使用する必要がない場合は、ユーザー定義のコレクションを使用し、ユーザー定義のコレクションを使用して一括でレコードを挿入する方がよいでしょう。サンプルの例が見つかります。 – Meena