My project has two parts : a Powershell script which collect some data and an ASP.NET 4.5 MVC application (with Entity Framework 6.1.3) which receive the data (as a file) and integrate them into the DB. There are more or less 1500 files that would be sent to the ASP.NET application.
I need to use transactions : If an error occurred while adding the data to the DB, nothing must be added (rollback). It wasn't a problem to add this function. But it seems that when a transaction begin, another can't begin until the first is commited or rollbacked. It is bad because my 1500 files must wait one by one to be added, and as the integration time is +/- 5min, it takes TOO much time.
I don't know where I have made a mistake. Here is what my code looks like :
public bool JsonToDB(dynamic data)
{
using (MyEntities context = new MyEntities())
{
context.Database.CommandTimeout = 300;
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;
using (var transaction = context.Database.BeginTransaction(IsolationLevel.ReadUncommitted))
{
try
{
// DB integration from the file provided by the Powershell script.
context.SaveChanges();
transaction.Commit();
transaction.Dispose();
return true;
}
catch (Exception e)
{
// Error management.
transaction.Rollback();
transaction.Dispose();
return false;
}
}
}
}
public Task FileIntegration(string fileDirectory, string fileName)
{
return Task.Factory.StartNew(() =>
{
try
{
string fileContent = System.IO.File.ReadAllText(fileDirectory + "JSON/" + fileName, Encoding.ASCII);
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic data = serializer.Deserialize(fileContent, typeof(object));
if (JsonToDB(data))
{
System.IO.Directory.Move(fileDirectory + "JSON/" + fileName, fileDirectory + "JSON/Success/" + fileName);
}
else
{
System.IO.Directory.Move(fileDirectory + "JSON/" + fileName, fileDirectory + "JSON/Error/" + fileName);
}
}
catch(Exception e)
{
System.IO.Directory.Move(fileDirectory + "JSON/" + fileName, fileDirectory + "JSON/Error/" + fileName);
}
});
}
[HttpPost]
[AllowAnonymous]
public ActionResult Receive(HttpPostedFileWrapper file)
{
try
{
file.SaveAs(Server.MapPath("~") + "/Files/JSON/" + file.FileName);
HostingEnvironment.QueueBackgroundWorkItem(ct => {
return FileIntegration(Server.MapPath("~") + "/Files/", file.FileName);
});
}
catch (Exception e)
{
return new HttpStatusCodeResult(400, "Unable to save the JSON file. Detailed error: " + e.Message);
}
return new HttpStatusCodeResult(200, "OK");
}
I also tried to use SaveChangesAsync method to save the changes (https://stackoverflow.com/a/28133913) but an error occurred:
An error was reported while committing a database transaction but it could not be determined whether the transaction succeeded or failed on the database server.
Do you have some ideas to help me solving this problem?
Thanks in advance.
Edit : To be more clear : It is the instruction context.SaveChanges();
that can't be executed for multiple transaction at the same time. To apply its changes, a transaction must wait the end of the other changes application. What I want is to be able to have multiple method instances saving their changes without waiting. DB integration only consists of inserts and deletes in the DB (no updates).