Task.Run вызывает исключение «Невозможно получить доступ к удаленному экземпляру контекста»C#

Место общения программистов C#
Ответить
Anonymous
 Task.Run вызывает исключение «Невозможно получить доступ к удаленному экземпляру контекста»

Сообщение Anonymous »

Использование Task.Run вызывает в моем приложении исключение «удаленный объект» при использовании DbContext.
Код выглядит так (см. всю цепочку):
UserController.cs

Код: Выделить всё

[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly UserService userService;

/// 
/// 
/// 

public UsersController(UserService userService)
{
this.userService = userService;
}

public async Task DoSomething()
{
await this.userService.MyMethod();
return this.Ok();
}
}
UserService.cs

Код: Выделить всё

public class UserService
{
private readonly UserRepository userRepository;

public UserService(UserRepository userRepository)
{
this.userRepository = userRepository;
}

public async Task MyMethod()
{
// some logic
Task.Run(() => MethodCallAsync());
}

void MethodCallAsync()
{
// some logic
// calls UserRepository, which uses the DbContext by DI
}
}
Репозиторий пользователей:

Код: Выделить всё

public class UserRepository
{
private MyDbContext dbContext;

public UserRepository(MyDbContext dbContext)
{
this.dbContext = dbContext;
}

public async Task DoSomethingToo(string username)
{
var user = await this.dbContext.Users.SingleOrDefaultAsync(u => u.Username == username);
// some logic
}
}
Вызывает следующее исключение (сообщение):

Невозможно получить доступ к удаленному экземпляру контекста. Распространенной причиной этой ошибки является удаление экземпляра контекста, который был разрешен в результате внедрения зависимостей, а затем попытка использовать тот же экземпляр контекста в другом месте вашего приложения. Это может произойти, если вы вызываете Dispose для экземпляра контекста или заключаете его в оператор using. Если вы используете внедрение зависимостей, вы должны позволить контейнеру внедрения зависимостей позаботиться об удалении экземпляров контекста.

Как я настроил контекст базы данных и UserRepository:
Startup.cs:

Код: Выделить всё

    public void ConfigureServices(IServiceCollection services)
{
// some logic
if (MyDbContextFactory.GetConnectionString() != null)
{
services.AddDbContext(options => options.UseMySQL(MyDbContextFactory.GetConnectionString())
.LogTo(s => System.Diagnostics.Debug.WriteLine(s)));
}

services.AddScoped(typeof(UserService));
services.AddScoped(typeof(UserRepository));
// some logic
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// some logic
using (var serviceScope = app.ApplicationServices.CreateScope())
{
var dbContext = serviceScope.ServiceProvider.GetService();

if (dbContext != null)
{
dbContext.Database.Migrate();
}
}
// some logic
}

public class MysqlEntityFrameworkDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
{
serviceCollection.AddEntityFrameworkMySQL();
new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection)
.TryAddCoreServices();
}
}
MyDbContextFactory.cs

Код: Выделить всё

    public MyDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseMySQL(GetConnectionString());
return new MyDbContext(optionsBuilder.Options);
}
Если я заменю Task.Run на BackgroundJob.Enqueue, все будет работать нормально. Но Hangfire создает много (>1к) записей в Redis в течение нескольких минут, так как этот метод вызывается очень часто. Кроме того, если он работает с зависанием, он должен работать и с Task.Run,

Подробнее здесь: https://stackoverflow.com/questions/756 ... -exception
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»