Reputation: 759
Is there a way to execute multiple insert statement using ExecuteStoreCommand in EF? I am using a StringBuilder to generate the multiple insert statements. The code basically looks like this
StringBuilder _saveReasonQuery = new StringBuilder();
public void ApplyRules()
{
using(var context = new SpecializedDBEntities())
{
foreach(var item in list)
{
//Do something
SaveReason(item, reasonId);
}
context.GetObjectContext().ExecuteStoreCommand(_saveReasonQuery.ToString());
ctx.SaveChanges();
}
}
//Inside Save Reason
public void SaveReason(...)
{
_saveReasonQuery.Append("INSERT INTO ORDER_IMPLEM_DTL_REASON ");
_saveReasonQuery.Append("(ORDER_IMPLEM_REASON_ID, SALES_ORDER_IMPLEM_DTL_ID, REASON_ID, REASON_STAT_ID, SALES_ORDER_BRDCST_ID, CREA_BY, CREA_DT)");
_saveReasonQuery.Append(" VALUES ");
_saveReasonQuery.Append(String.Format("('0', '{0}', '{1}', '{2}', '{3}', '{4}', TO_DATE('{5}', 'YY-MM-DD HH:mi'));",
orderSpot.SALES_ORDER_IMPLEM_DTL_ID, reasonId, Common.Convert_Int64(orderSpot.CUESHT_STAT_ID),
orderSpot.SALES_ORDER_DTL_BRDCST_ID, userContext.User.USER_CD, DateTime.Now.ToUniversalTime().ToString("yy-MM-dd hh:mm")));
}
However, an Invalid Character error occurs when the query is executed by EF. I did some research and found out that it was the semicolon that was generating this error. But I can't remove the semicolon since its the 'end of the line' for Oracle. Any suggestions?
Also, I executed the generated string from the StringBuilder directly against the Database and it works for inserting 5 rows.
Upvotes: 2
Views: 1942
Reputation: 759
I found the solution by trial and error.
It turns out, you need to enclose your multiple insert inside a BEGIN...END; statement, to enable the semicolon to be read as end-of-line delimiter.
My code now would read like:
StringBuilder _saveReasonQuery = new StringBuilder();
public void ApplyRules()
{
using(var context = new SpecializedDBEntities())
{
_saveReasonQuery.Append("BEGIN ");
foreach(var item in list)
{
//Do something
SaveReason(item, reasonId);
}
_saveReasonQuery.Append("END;");
context.GetObjectContext().ExecuteStoreCommand(_saveReasonQuery.ToString());
ctx.SaveChanges();
}
}
//Inside Save Reason
public void SaveReason(...)
{
_saveReasonQuery.Append("INSERT INTO ORDER_IMPLEM_DTL_REASON ");
_saveReasonQuery.Append("(ORDER_IMPLEM_REASON_ID, SALES_ORDER_IMPLEM_DTL_ID, REASON_ID, REASON_STAT_ID, SALES_ORDER_BRDCST_ID, CREA_BY, CREA_DT)");
_saveReasonQuery.Append(" VALUES ");
_saveReasonQuery.Append(String.Format("('0', '{0}', '{1}', '{2}', '{3}', '{4}', TO_DATE('{5}', 'YY-MM-DD HH:mi'));",
orderSpot.SALES_ORDER_IMPLEM_DTL_ID, reasonId, Common.Convert_Int64(orderSpot.CUESHT_STAT_ID),
orderSpot.SALES_ORDER_DTL_BRDCST_ID, userContext.User.USER_CD, DateTime.Now.ToUniversalTime().ToString("yy-MM-dd hh:mm")));
}
Upvotes: 1
Reputation: 14580
Both ObjectContext.ExecuteStoreCommand
and the newer DbContext.ExecuteSqlCommand
as implied in their name will only execute a single command. I suggest you build up your commands in a List<>
of update statements and execute them sequentially when they are all ready ...
public void ApplyRules()
{
var saveQueries = new List<Tuple<string, object[]>>();
foreach(var item in list)
{
//Do something
saveQueries.Add(SaveQuery(reasonId, ...));
}
using(var context = new SpecializedDBEntities())
{
foreach(var saveQuery in saveQueries)
{
testContext.Database.ExecuteSqlCommand(saveQuery.Item1, saveQuery.Item2);
}
ctx.SaveChanges();
}
}
private Tuple<string, object[]> SaveQuery(int reasonId, ...)
{
const string query =
"INSERT INTO ORDER_IMPLEM_DTL_REASON " +
"(ORDER_IMPLEM_REASON_ID, SALES_ORDER_IMPLEM_DTL_ID, REASON_ID, REASON_STAT_ID, SALES_ORDER_BRDCST_ID, CREA_BY, CREA_DT)" +
" VALUES {0}, {0}, {1}, {2}, {3}, {4}, {5}";
object[] values = new object[]{
orderSpot.SALES_ORDER_IMPLEM_DTL_ID,
reasonId,
Common.Convert_Int64(orderSpot.CUESHT_STAT_ID),
orderSpot.SALES_ORDER_DTL_BRDCST_ID,
userContext.User.USER_CD,
DateTime.Now.ToUniversalTime().ToString("yy-MM-dd hh:mm")
};
return new Tuple<string, object[]>(query, values);
}
Upvotes: 0