EF множественный dbcontext выдает различные исключения при запуске с высоким запросом параллелизма - PullRequest
0 голосов
/ 08 июня 2018

я ссылаюсь на проект ApiLog (библиотека C #, записываю логи в базу данных в IActionFilter) в бизнес-проект (web api), оба они определяют свой собственный DbContext , с именами LogContext и BusinessContext:

public class LogContext:DbContext
{
    public DbSet<ApiLogBase> LogBases { get; set; }
}

 public class BusinessContext:
{
 public DbSet<lsapi.Models.Company> Companys { get; set; }
 public DbSet<lsapi.Models.CompanyFee> CompanyFees { get; set; }
}

они кэшируются в CallContext и вызываются в репозитории

public static BusinessContext GetCurrDBContext()
    {
         BusinessContext ctx= (BusinessContext)CallContext.GetData("cachekey");
        if (ctx == null)
        {
            ctx = new BusinessContext();
            CallContext.SetData("cachekey", ctx);
        }
        return ctx;
    }

LogContext, используемый в репозитории,

     public LogRepository(string connectionString)
    {
        var logContextData = CallContext.GetData(logContextKey);
        if (logContextData == null)
        {
            LogContext logContext = new LogContext(connectionString);
            logContext.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
            CallContext.SetData(logContextKey, logContext);
            db = logContext;
        }
        else
        {
            db = (LogContext)logContextData;
        }
    }

, а репозиторий внедряется в приложение, а приложение внедряется в клиентаIActionFilter:

 public class APILogActionFilter : IActionFilter
{
    ILogApplication logapp;

    public APILogActionFilter(ILogApplication logapp)
    {
        this.logapp= logapp;

    }

все вышеперечисленное (репозиторий, приложение, iactionfilter) зарегистрировано в caslt.windsor:

public class Installer : IWindsorInstaller
{
    string logConnectionStringName;
    public Installer(string logConnectionStringName )
    {
        this.logConnectionStringName = logConnectionStringName;
    }
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {

        //db
        container.Register(Component.For< ILogRepository>().ImplementedBy<LogRepository>()
            .DependsOn(Dependency.OnValue("connectionString", logConnectionStringName))
            );
        //application
        container.Register(Component.For< ILogApplication>().ImplementedBy<LogApplication>());
        //actionfilterattrite
        container.Register(Component.For<IActionFilter>().ImplementedBy<APILogActionFilter>());

    }
}

они загружаются в проекте Global.ascx.cs of Business101

using ApiLog;
public class bootstrap
{
    static IWindsorContainer container;
    public static IWindsorContainer Container { get { return container; } }
    public static void Boot()
    {
        container = new WindsorContainer();

        container.Install(new 
   ApiLog.Installer(connectionstring));


    }
}

 public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
         .......
         bootstrap.Boot();
        ...
        //warm up BusinessContext
       var objectContext = ((IObjectContextAdapter)BusinessContext.GetCurrDBContext()).ObjectContext;
        var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);


    }
}

API работает нормально.но если я непрерывно нажимаю f5 непрерывно (7-13 раз) после свежей сборки, выкидываются различные исключения (пока 4 типа исключений):

  Server Error in '/' Application.
--------------------------------------------------------------------------------
SqlConnection does not support parallel transactions.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: SqlConnection does not support parallel transactions.

Source Error: 

Line 45:         {Line 46:             db.LogBases.Add(log);Line 47:             db.SaveChanges();Line 48:         }Line 49:         public ApiLogBase GetOne(int id)

Source File: C:\Dev\code\ls_server\zjwist.log\ZJWistLog\LogRepository.cs    Line: 47 




Server Error in '/' Application.
--------------------------------------------------------------------------------
There is already an open DataReader associated with this Command which must be closed first.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.

Source Error: 

Line 45:         {Line 46:             db.LogBases.Add(log);Line 47:             db.SaveChanges();Line 48:         }Line 49:         public ApiLogBase GetOne(int id)


Server Error in '/' Application.
--------------------------------------------------------------------------------
The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.

Source Error: 

Line 44:         public void AddLog(ApiLogBase log)Line 45:         {Line 46:             db.LogBases.Add(log);Line 47:             db.SaveChanges();Line 48:         }

Source File: C:\Dev\code\ls_server\zjwist.log\ZJWistLog\LogRepository.cs    Line: 46 


Server Error in '/' Application.
--------------------------------------------------------------------------------
ExecuteReader requires an open and available Connection. The connection's current state is open.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is open.

Source Error: 

Line 45:         {Line 46:             db.LogBases.Add(log);Line 47:             db.SaveChanges();Line 48:         }Line 49:         public ApiLogBase GetOne(int id)

Source File: C:\Dev\code\ls_server\zjwist.log\ZJWistLog\LogRepository.cs    Line: 47 

любое предположение будет предотвращено.

1 Ответ

0 голосов
/ 27 июня 2018

Я думаю, я нашел, где проблема.это находится в конструкторе LogRepository.конструктор будет вызываться только один раз за время существования приложения, потому что синглтон - это стиль жизни Castle.Windsor по умолчанию, поэтому logContext не может быть обновлен в последующих запросах, он всегда будет первым при запуске приложения (iis website /запуск apppool) , как сказал Герт Арнольд, «один кешированный контекст».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...