Reputation: 28760
I have a DBContext helper class that uses extension methods:
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);
}
}
Are extension methods a bad fit for this as they might be accessed by different threads causing problems?
Upvotes: 1
Views: 1312
Reputation: 8197
Extensions methods may be thread safe, and may be thread unsafe depending how you write them.
Your method is thread safe while each DbContext
is accessed from different thread. This is reasonable restriction, cause DbContext
is not really thread-safe class. (Enabling Multiple Active Result Sets you can remove this restriction, but it's not good decision cause DbContext
tracks data).
It's good practice to create DbContext
for a single business operation and immediately dispose it — it's the way of the Unit Of Work pattern.
F.e. in Web API scenario you can create different DbContext
for each HTTP request or even you can create different context for each operation:
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);
}
}
}
The method FindAsync
works correctly in this code, although it is not convenient to call. I would change the signature:
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);
}
}
}
Upvotes: 1