Getting \"new transaction is not allowed because there are other threads running in the session\".
It has nothing to do with foreach loops or anything people usually
You don't dispose the context when your request is finished. You can dispose the context either by applying a using block ...
using (var context = new MyContext())
{
// Do Db stuff and SaveChanges, etc.
}
// context gets disposed automatically here
... or explicitly:
context.Dispose();
(That's my theory based on your input so far.)
Try this code. It may help. In this code, I take all of the IDs from the database and iterate over them with a new object of the database context named ctx
:
var listOfCourseId = db.Courses.Where(c => c.CourseStatus == 1).Select(c => c.CourseId);
using (var ctx = new UniversityDbContext())
{
foreach (var acourseId in listOfCourseId)
{
Course selectedCors = new Course();
selectedCors = ctx.Courses.Where(id => id.CourseId == acourseId).Single(); //hence use ctx.tableName instead of db.tableName
selectedCors.CourseStatus = 0;
ctx.Entry(selectedCors).State = EntityState.Modified;
ctx.SaveChanges();
}
}
I don't think that this is only problem of not disposed contexts (context doesn't keep opened transaction - you would see it because of uncommitted changes). If you have this problem you most probably don't use the new context instance per request or you have some multi threaded / asynchronous processing on the shared context instance (= one connection). This exception says that multiple threads (probably multiple processed requests) are trying to use their own transaction on the same connection - that is not possible.
Corner case can be manual handling of connections provided to context but I guess you would mention it if you use it.
Edit:
Your factory doesn't provide per request context - it provides single context for all request!!! That static dictionary is shared among all request so the first creates instance and stores it under _DEFAULT
key and all other requests will use it.
It has to do with the new EF4 implicit Transaction.
This means that when opening an AsEnumerable() or ObjectQuery Entity request, you are in a transaction, one way to evade it is to AsArray() the query, and then you are no longer in the transaction. Another would be by shutting down the transaction maybe with optimistic locking ? but i cant find it.
this is my solution
RespondableSites = model.HyperTextLinkEntitySets.OfType<Site>()
.Where(x =>
(
x.moz_RESPONSEDATA != null
&& x.RowState.IndexOf("a=") < 0))
).ToArray();
foreach (var siteObj in RespondableSites)
{
using (var context = new brandshieldDBEntities())
{
ParseResponseData(siteObj);
model.SaveChanges();
}
}
and it works, it's slow but it works..
check here: SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session