Kal*_*exx 30 c# entity-framework ef-code-first entity-framework-4.1
看看我的Elmah错误日志,我看到InvalidOperationException来自Entity Framework 的一些s处理:
The context cannot be used while the model is being created.
Run Code Online (Sandbox Code Playgroud)
这是Nuget最新的EF CodeFirst库.我能够在网上找到的唯一信息是,它是由数据上下文作为单例引起的,这当然不是我的情况.在我的Windsor安装程序中,我的EF工作单元结构正在注册:
container.Register(Component.For<IUnitOfWork>()
.ImplementedBy<EFUnitOfWork>()
.LifeStyle
.PerWebRequest);
Run Code Online (Sandbox Code Playgroud)
我能够通过在VS中点击F5来重新创建错误以启动调试会话,并且当IIS正在启动时,将第二个网页加载到调试会话.
我怀疑这是因为用户试图访问系统而Asp.net由于缺乏活动而卸载,这是有道理的,因为我的产品目前处于非常小的beta测试中.但是,由于真实的人正在使用带有实时数据的网站,我需要尽可能少的错误.
有谁知道如何防止这种情况发生?
container.Register(Component.For<IUnitOfWork>().ImplementedBy<EFUnitOfWork>().LifeStyle.PerWebRequest);
using (var context = new MyJobLeadsDbContext())
{
context.Set<UnitTestEntity>().Any();
}
Run Code Online (Sandbox Code Playgroud)
但是,当我在IIS加载应用程序时尝试执行第二个Web请求时,仍会发生上一个错误
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)
at MyApp.DomainModel.Queries.Users.UserByEmailQuery.Execute() in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp.DomainModel\Queries\Users\UserByEmailQuery.cs:line 44
at MyApp.Infrastructure.MyAppMembershipProvider.GetUser(String email, Boolean userIsOnline) in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp\Infrastructure\MyAppMembershipProvider.cs:line 102
at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline)
at System.Web.Security.Membership.GetUser()
at MyApp.MyAppBaseController.Initialize(RequestContext requestContext) in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp\MyAppBaseController.cs:line 23
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Run Code Online (Sandbox Code Playgroud)
Kal*_*exx 17
我终于找到了这个的真正原因,至少对我而言.
问题是我DbContext在我的自定义Asp.Net会员提供商中从Windsor 检索了一个.这导致了一个问题,因为成员资格提供程序具有整个应用程序的生命周期,而对于db上下文的所有其他检索调用都是针对特定Web请求的新数据库上下文.这意味着两个数据库上下文同时"旋转",因此抛出了这个错误.
这也导致了许多难以调试的实体缓存问题,因此任何在其成员资格提供程序中使用EF的人都需要真正关注其上下文生命周期.
例如:
public class CustomMembershipProvider : MembershipProvider
{
private IServiceFactory _serviceFactory;
public CustomMembershipProvider() : this(null) { }
public CustomMembershipProvider(IServiceFactory factory)
{
// IF no factory was provided, we need to get one from the bootstrapper
if (factory == null)
_serviceFactory = new WindsorServiceFactory(Bootstrapper.WindsorContainer);
else
_serviceFactory = factory;
}
public override string ResetPassword(string email, string answer)
{
var unitOfWork = GetUnitOfWork();
return new ResetUserPasswordCommand(unitOfWork).WithUserEmail(email).Execute();
}
private IUnitOfWork GetUnitOfWork()
{
return _serviceFactory.GetService<IUnitOfWork>();
}
}
Run Code Online (Sandbox Code Playgroud)
这个想法是成员资格提供程序执行的任何操作都UnitOfWork从Windsor 获取类,并使用它来执行操作(在这种情况下,我的UnitOfWork类是一个存储库持有者来包装我的EF数据上下文)
我在多线程WPF应用程序中遇到了同样的问题.
我的解决方法是强制从Windsor安装程序初始化DbContext:
container.Register(Component.For(TheDbContext.Blah.Blah));
using (var context = new TheDbContext())
context.Set<SomeRandomEntity>().Any();
Run Code Online (Sandbox Code Playgroud)
我可能会补充一点,我认为这可以作为EF中的错误:它们应该使用线程安全(带锁或其他)代码进行DbContext初始化.
当然,更好的解决方案是NHibernate所做的:它SessionFactory是一个明确创建的独立对象Session.
| 归档时间: |
|
| 查看次数: |
28002 次 |
| 最近记录: |