2017-12-16 7 views
1

私はEntity Frameworkに関する多くの経験がありませんので、できるだけ多くの情報を提供し、あまり長くしないようにしています。エンティティフレームワークDbContextインスタンスDataReaderが既に開いています

これは私のDbContextです:

var user = ContextFactory.Instance.Users.FirstOrDefault(x => x.id == id); 
var dealerships = ContextFactory.Instance.Dealership.ToList(); 

をそして、それが正常に動作している:だから

using MySql.Data.Entity; 
using MySql.Data.MySqlClient; 
using System; 
using System.Data.Entity; 
using System.Data.Entity.Infrastructure; 
using System.Data.Entity.Migrations; 

namespace src.Database.Models 
{ 
    [DbConfigurationType(typeof(MySqlEFConfiguration))] 
    public class DefaultDbContext : DbContext 
    { 
     public DefaultDbContext(string connectionString) : base(connectionString) 
     { 
      System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<DefaultDbContext, MigrationConfiguration>()); 
     } 

     public DbSet<User> Users { get; set; } 
     public DbSet<Character> Characters { get; set; } 
     public DbSet<CharacterClothes> CharacterClothes { get; set; } 
     public DbSet<CharacterVehicles> CharacterVehicles { get; set; } 
     public DbSet<Dealership> Dealership { get; set; } 
     public DbSet<DealershipVehicle> DealershipVehicles { get; set; } 
    } 

    public class ContextFactory : IDbContextFactory<DefaultDbContext> 
    { 
     private static string ConnectionString; 

     public static void SetConnectionParameters(string serverAddress, string username, string password, string database, uint port = 3306) 
     { 
      var connectionStringBuilder = new MySqlConnectionStringBuilder() 
      { 
       Server = serverAddress, 
       UserID = username, 
       Password = password, 
       Database = database, 
       Port = port 
      }; 

      ConnectionString = connectionStringBuilder.ToString(); 
     } 

     private static DefaultDbContext _instance; 

     public static DefaultDbContext Instance 
     { 
      get 
      { 
       if (_instance != null) return _instance; 
       return _instance = new ContextFactory().Create(); 
      } 
      private set { } 
     } 

     public DefaultDbContext Create() 
     { 
      if (string.IsNullOrEmpty(ConnectionString)) throw new InvalidOperationException("Please set the connection parameters before trying to instantiate a database connection."); 

      return new DefaultDbContext(ConnectionString); 
     } 
    } 

    internal sealed class MigrationConfiguration : DbMigrationsConfiguration<DefaultDbContext> 
    { 
     public MigrationConfiguration() 
     { 
      AutomaticMigrationsEnabled = true; 
      AutomaticMigrationDataLossAllowed = true; 
      SetSqlGenerator("MySql.Data.MySqlClient", new MySqlMigrationSqlGenerator()); 
     } 
    } 
} 

、それは私がこのようにアクセスするすべての接続のためのインスタンスを使用しています!

ものの、時折私はこのエラーを取得する:

は、最初に閉じる必要があります。この接続に関連付けられているオープンDataReaderが既にあります。

これは、すでに使用中のインスタンスを使用しようとしているからだと思います。

私はそれを修正する方法についての日を探していましたが、まだそれを動作させることができませんでした。私はMultipleActiveResultSetsについて読んだことがありますが、私はMySQLを使用しており、それはサポートされていないようです。

+2

** Entity Framework DbContextにシングルトンを使用しないでください。シングルトンはアンチパターンであるだけでなく、EFでできる最悪のことです。 –

+0

私は考えました、このような何かをやっていますか? '(var ctx = new ContextFactory()。Create()) { // crud }}' – Wuzi

答えて

0

あなたはそれが

private static DefaultDbContext _instance; 

スレッド/リクエストあたりのための新しいDBContextインスタンスを作成するには良いかもしれ

[ThreadStatic] 
private static DefaultDbContext _instance; 

に変更する必要があります。同じDbContextをスレッドで共有することは危険であり、好ましくありません。別のスレッドがすでに使用されている同じDBContextインスタンスを使用しようとする原因になります。

また、のUnitOfWork、トランザクション管理およびごとにスレッド/要求に対してDbContextを作成する利点については非常に良い記事hereがあります。

+0

ありがとうございます!ええ、そうです。私はそれをリファクタリングして、リクエストごとに新しいものを作るべきですが、これは今のところやります! – Wuzi

関連する問題