Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework,There is already an open DataReader associated with this Connection which must be closed first

In the "each", when run the "FirstOrDefault" will error "There is already an open DataReader associated with this Connection which must be closed first.". How to do ?

public int SetUser(string[] dIds, string pId)
{
    using (var scope = _dbContextScopeFactory.Create())
    {
        var db = scope.DbContexts.Get<JuCheapContext>();

        var users = db.Users;

        var user = users.FirstOrDefault(m => m.Id == pId);
        if (user.Places == null)
        {
            user.Places = new List<PlaceEntity>();
        }

        var place = db.Place.Include(m => m.User).Where(m => dIds.Contains(m.Id));

        place.Each(m =>
        {
            user.Places.Add(m);

            //There is already an open DataReader associated with this Connection which must be closed first.
            var pu = users.FirstOrDefault(u => u.LoginName == m.Key);

            if (pu != null)
            {
                pu.FId = pId;
            }

        });

        return db.SaveChanges();
    }
}
like image 777
clark wu Avatar asked Apr 06 '17 19:04

clark wu


2 Answers

When you say

place.Each(m =>

You're using a reader to iterate the items from the database

Then

  var pu = users.FirstOrDefault(u => u.LoginName == m.Key);

The second reader enters while the first one is still executing and the error occurs

Call ToList() to get the data into memory and close the reader

var place = db.Place.Include(m => m.User).Where(m => dIds.Contains(m.Id)).ToList();

You can also enable MARS (Multiple Active Result Sets)

https://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.110).aspx

like image 168
The One Avatar answered Oct 18 '22 03:10

The One


If you are using SQL, another approach is to set: MultipleActiveResultSets=true in your connection string, so you can have multiple datareaders

like image 1
Anderson Luiz Ferrari Avatar answered Oct 18 '22 04:10

Anderson Luiz Ferrari