我有一个使用扩展方法的 DBContext助手类:
public static class DBContextHelper
{
public static async Task<T> FindAsync<T>(
this DBContext context,
Expression<Func<T, bool>> match)
where T : BaseEntity
{
return await context.Set<T>().SingleOrDefaultAsync(match);
}
}
扩展方法是否适合这种情况,因为它们可能被不同的线程访问而导致问题?
答案 0 :(得分:1)
扩展方法可能是线程安全的,并且根据您编写它们的方式可能是线程不安全的。
从不同的线程访问每个DbContext
时,您的方法是线程安全的。这是合理的限制,因为DbContext
不是真正的线程安全类。 (启用Multiple Active Result Sets您可以删除此限制,但这不是一个好的决定原因DbContext
tracks data)。
为单个业务操作创建DbContext
并立即处置它是一种很好的做法 - 它是way of the Unit Of Work pattern。
F.e。在Web API场景中,您可以为每个HTTP请求创建不同的DbContext
,甚至可以为每个操作创建不同的上下文:
public class UserRepository : IUserRepository
{
public User async GetByIdAsync(int id)
{
using (var dbContext = new MyDbContext())
{
var data = await dbContext.FindAsync((UserData user) => user.Id == id);
return new User(data);
}
}
}
方法FindAsync
在此代码中正常工作,但调用不方便。我会改变签名:
public static class DBSetHelper
{
public static async Task<T> FindAsync<T>(
this DbSet<T> set,
Expression<Func<T, bool>> match)
where T : BaseEntity
{
return await set.SingleOrDefaultAsync(match);
}
}
. . .
public class UserRepository : IUserRepository
{
public User async GetByIdAsync(int id)
{
using (var dbContext = new MyDbContext())
{
var data = await dbContext.Users.FindAsync(user => user.Id == id);
return new User(data);
}
}
}