我引用了一个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;
}
Repository中使用的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;
}
}
,将存储库注入到Application中,并将应用程序注入客户IActionFilter:
public class APILogActionFilter : IActionFilter
{
ILogApplication logapp;
public APILogActionFilter(ILogApplication logapp)
{
this.logapp= logapp;
}
以上所有(repository,application,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>());
}
}
它们在Business项目的Global.ascx.cs中被引导。
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
任何建议都会被预先确定。
答案 0 :(得分:0)
我想我找到了问题所在。它在LogRepository的构造函数中。由于Singleton是Castle.Windsor的默认生活方式,因此在应用程序的生命周期中只会对建设者进行一次攻击,因此logContext没有机会在以后的请求中进行更新,它始终是应用程序启动时的第一个(iis网站/ apppool start),正如Gert Arnold所说的,“一个缓存的上下文”。