2016-08-30 26 views
1

私は拡張メソッドを使用していますDBContextヘルパークラスがあります。彼らは問題を引き起こし、異なるスレッドによってアクセスされる可能性があるとしてEF6 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); 
    } 
} 

は、このために悪いフィット拡張メソッドはありますか?

答えて

1

拡張メソッドはスレッドセーフである可能性があり、スレッドの書き方によってスレッドが安全でない可能性があります。

あなたのメソッドはスレッドセーフですが、DbContextは別のスレッドからアクセスされます。これは妥当な制限であり、理由はDbContextは実際にスレッドセーフなクラスではありません。 (Multiple Active Result Setsを有効にするとこの制限は取り除くことができますが、それは良い判断の原因ではありませんDbContexttracks data)。

これは、単一の事業運営のためのDbContextを作成することをお勧めしますし、すぐににそれを処分する - それはway of the Unit Of Work patternです。

F.e.ウェブ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); 
     } 
    } 
}