The context cannot be used while the model is being created exception

async-await c# entity-framework

Question

I've got the following error using Entity Framework 6.0.0.0.

The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the
OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe. It is fired inside an async method ,upd:

   public async Task<IList<Model>> GetEntities(filter f)
   {
        using (var db = new MyDbContext())
        { 
           var query = db.MyDbSet.AsQueryable();

            if (f != null && f.field.Any())
               //Exception throwed here
                query = query.Where(a => f.field.Contains(a.field));

        return await query.ToListAsync();
       }
 }

But any await calls or other multithreading operation is not performed when i try to find my entities by Where clause.

Are any suggestions related to that issue ? I found a lot of answers but didn't found their helpful for me.

1
3
10/31/2015 6:44:39 PM

Popular Answer

You want to implement a proper method of connecting to your database that disposes the connection, or uses a term called "dependency injection" - creating an interface and instance of the DataContext that is able to be accessed at any time by any function in the controller. Here are examples of the 2 methods:

Dispose Architecture

This architecture requires that you declare your DataContext before any other function, and add a Dispose function in the Controller at the end.

Some specific oddities I found and fixed in the code:

  • You should be returning a ViewModel or a data model that represents a database table or view you are querying, in this case MyDbSet, not Model.
  • You should be using the db instance declared generically for the class.
  • You should define what filter is. An array? A model? A string? I'm going to assume it's a list of strings like this: string[] filter = { "Fruits", "Meats", "Dairy" };
  • The Where clause might not be correct on your query, but again, I don't know what your filter looks like. There's other examples here: https://docs.microsoft.com/en-us/dotnet/api/system.linq.queryable.where?view=netframework-4.8

    MyDbContext db = new MyDbContext();
    
    public async Task<IList<MyDbSet>> GetEntities(filter f)
    {
        using (db)
        { 
            var query = null;
            if (f != null && f.field.Any())
            {
                query = db.MyDbSet.AsQueryable().Where((a, index) => a == f);
            }
            return await query.ToListAsync();
        }
    }
    
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }
    

Dependency Injection

I describe this process thoroughly in another SO post, here:

How to inject my dbContext with Unity

The main difference is you would do something like this in your controller's GetEntities function to get the data:

query = repository.GetMyDbSet.Where((a, index) => a == f);

Mostly the same as above, but you don't need the using(db) { ... } statement, anymore.

You would have an interface:

public interface IDataRepository
{
    void SaveChanges();
    IEnumerable<MyDbSet> GetMyDbSet();
}

and a repository class function to return the data to you:

public IEnumerable<MyDbSet> GetMyDbSet()
{
    return context.MyDbSet;
}

And context is defined in a Repository class:

public class DataRepository : IDataRepository
{
    private bool disposing;
    private readonly MyDbContext context;

    public virtual void Dispose()
    {
        if (disposing)
        {
            return;
        }

        disposing = true;

        if (context != null)
        {
            context.Dispose();
        }
    }

    public void SaveChanges()
    {
        context.SaveChanges();
    }

    public DataRepository()
    {
        context = new MyDbContext();
        context.Configuration.ProxyCreationEnabled = false;
    }

    public IEnumerable<MyDbSet> GetMyDbSet()
    {
        return context.MyDbSet;
    }
}

Hopefully this helps you or someone.

0
2/6/2020 6:54:12 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow