EF Core怪问题之通过依赖注入获取的上下文在执行异步写入数据库时抛出异常?
此问题实质上是上下文生命周期的问题, 网上有篇文章对此问题分析的更加详细, 请参考:
http://www.tnblog.net/aojiancc2/article/details/3283
出问题的代码如下:
public class DBBookChaptersService : IBookChaptersService { private readonly BooksContext _booksContext; public DBBookChaptersService(BooksContext booksContext) { _booksContext = booksContext;} public async Task Add(BookChapter bookChapter) { await _booksContext.Chapters.AddAsync(bookChapter); await _booksContext.SaveChangesAsync(); //此处写入数据库时会抛出异常 } }
经分析查找原因如下:
通过依赖注入的上下文执行到SaveChangesAsync这个异步方法时,会直接Dispose掉, 导致回调失败.
解决办法:
1. 使用同步方法SaveChanges().
此方法最简单, 也可以新构造一个异步方法将其包起来实现异步调用.
2. 不用依赖注入的上下文, 而是临时生成上下文, 具体步骤如下:
此方法并非完全不使用依赖注入, 只是舍弃依赖注入上下文,而使用依赖注入的DbContextOptions<T>来构造临时上下文.
public class DBBookChaptersService : IBookChaptersService { private readonly BooksContext _booksContext; // 1. 采用依赖注入获得DbContextOptions private readonly DbContextOptions<BooksContext> _options; public DBBookChaptersService(BooksContext booksContext, DbContextOptions<BooksContext> options) { _booksContext = booksContext; _options = options; } public async Task Add(BookChapter bookChapter) { // 2. 用optins生成临时上下文, 执行异步SaveChangesAsync() using (var context = new BooksContext(_options)) { await context.Chapters.AddAsync(bookChapter); await context.SaveChangesAsync(); }
在网友的启发下, 发现Dispose的原因是上下文的生命周期问题. 可在注册服务时将其设为单例模式即可解决:
services.AddDbContext<BooksContext>(options => options.UseSqlServer( Configuration.GetConnectionString("BooksConnection")), ServiceLifetime.Singleton, ServiceLifetime.Singleton);