BlueshiftSoftware / EntityFrameworkCore

NoSQL providers for EntityFramework Core
Other
281 stars 57 forks source link

System.ObjectDisposedException: MongoDbQueryCompilationContextFactory #16

Closed rschaar closed 6 years ago

rschaar commented 7 years ago

Hello,

i have this issues: "ObjectDisposedException"

System.ObjectDisposedException: "Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances."

` public class MongoDbQueryCompilationContextFactory : QueryCompilationContextFactory { /// public MongoDbQueryCompilationContextFactory( [NotNull] QueryCompilationContextDependencies dependencies) : base(dependencies) { }

    /// <inheritdoc />
    public override QueryCompilationContext Create(bool async)
        => new QueryCompilationContext(
            Dependencies,
            async
                ? (ILinqOperatorProvider)new AsyncLinqOperatorProvider()
                : new LinqOperatorProvider(),
            `TrackQueryResults);

} `

crhairr commented 7 years ago

That type is actually a defunct holdover from when I was trying to get navigations to work. I've removed it. A new package has been built and deployed. Please let me know if you continue to see this error.

rschaar commented 7 years ago

Good Morning,

I solved the problem. Commenting out the MongoDbQueryCompilationContextFactory class only moves the problem to another class. This will cause the error to occur within the MongoDbDatabase class. I read that this problem should be solved by a new API. So please reinstall the class and try the following:

public override QueryCompilationContext Create (bool async)

         => new QueryCompilationContext (
             Dependencies,
             async
                 ? (ILinqOperatorProvider) new AsyncLinqOperatorProvider ()
                 : new LinqOperatorProvider (), true);

}

Instead of "TrackQueryResults", the value "true" must be used.

TrackQueryResults Edit

Gets a value indicating the default configured tracking behavior. C#

public virtual bool TrackQueryResults { get; }

Value System.Boolean

true if the default is to track query results, false if not.

MongoDbDatabase.cs:

/// public override Func<QueryContext, IAsyncEnumerable> CompileAsyncQuery(QueryModel queryModel) => queryContext => CompileQuery(queryModel)(queryContext) .ToAsyncEnumerable();

CompileQuery => System.ObjectDisposedException

crhairr commented 6 years ago

@rschaar, I think I've resolved this issue. After digging into the code, it looks like EF Core was making certain assumptions about what comes back from a query, and I was not properly working around all of those assumptions. It starts with something called a ValueBuffer inside of the QueryBuffer, which is used to map properties of hydrated objects. Since my library wraps the MongoDB C# driver, this is completely unnecessary and was causing a lot of null reference exceptions in certain queries.

To resolve it, I mapped my own MongoDbLinqOperatorProvider that removes the level of indirection from Linq that EF Core creates so that EntityQueryables map directly to Linq queries. I also rebuilt all of the relationship-handling query compilation code so that relationships are loaded correctly. I have a few more unit tests to add for more complex queries, but preliminary tests show that at least basic navigation queries using Include() work. Please give the latest preview build a try and let me know if it resolves your issue.

crhairr commented 6 years ago

There haven't been any updates in 4 months, but my tests appear to be working. I'm closing this unless instructions for reproducing the issue can be provided.

hanxinimm commented 6 years ago

@crhairr same issue

A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances

System.ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.\r\nObject name: 'KernelMongoDbContext'.\r\n at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()\r\n at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()\r\n at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker()\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompilationContextFactory.get_TrackQueryResults()\r\n at Microsoft.EntityFrameworkCore.MongoDB.Query.MongoDbQueryCompilationContextFactory.Create(Boolean async)\r\n at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)\r\n at Microsoft.EntityFrameworkCore.MongoDB.Storage.MongoDbDatabase.<>c__DisplayClass11_01.<CompileAsyncQuery>b__0(QueryContext queryContext)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteSingletonAsyncQuery[TResult](QueryContext queryContext, Func2 compiledQuery, IDiagnosticsLogger`1 logger, Type contextType)

fleed commented 6 years ago

@crhairr same issue using latest package (2.1.0-preview2-t006f54f83)

I'm using dependency injection in a Web API project. I define a scoped service and try to inject the data context defined using AddDbContext. If I use the context in write operations (e.g.: Add an item and save), that works. For read operations (using SingleOrDefaultAsync), that doesn't work.

My entity is defined as follows:

public class MigrationOperation
    {
        [JsonProperty("id")]
        [BsonId]
        [Key]
        public Guid Id { get; set; }

        [JsonProperty("request")]
        public MigrationRequest Request { get; set; }

        [JsonProperty("isCompleted")]
        public bool IsCompleted { get; set; }
    }

By design of the DbContext<> I must use scoped services.

Update: it looks like an issue with the async operations. If I use the SingleOrDefaultAsync operation, it only works the first time. If I use the SingleOrDefault operation, it works always

crhairr commented 6 years ago

That might have something to do with the underlying MongoDbConnection. I'll take a look.

It would be very helpful if you could fork this repo and make a unit test with the existing sample domain objects that reproduces the issue.

fleed commented 6 years ago

That might have something to do with the underlying MongoDbConnection. I'll take a look.

It would be very helpful if you could fork this repo and make a unit test with the existing sample domain objects that reproduces the issue.

I'll try