I have been using the new MVC framework with StructureMap recently and have had good results overall, however, I keep running into a very strange error that I cannot understand or work out how to resolve.
This is my architecture:
DBContext - linqToSql data context.
IRepository - contract defining data methods.
IService - contract defining service methods.
Controllers - two in this example.
I therefore have:
public class Repo : IRepository { public Repo(DBContext db) { ..... } } public class Service : IService { public Service(IRepository repo) { ..... } } public class ControllerOne : Controller { public ControllerOne(IService service) { ..... } } public class ControllerTwo : Controller { public ControllerTwo(IService service) { ..... } }
StructureMap is being used to define concrete types for IRepository and IService and the DBContext is constructed by the lamba expression - () => new DBContext() configured by DSL registry.
There is no caching of the DBContext at present
Onto the problem:
My index page loads and makes two simultaneous Ajax requests to ControllerOne and ControllerTwo, which are constructed via the StructureMap controller factory from MvcContrib.
StructureMap is injecting the concrete types of IService, which in turn are created with the configured IRepository instance and a new DBContext object.
ControllerOne is requesting a model from the IService instance, which is then returned as a JsonActionResult, which is rendered by Newtonsoft.Json.
ControllerTwo is requesting a different model from the IService instance, which is also serialised to a Json object when the MVC framework executes the ActionResult.
I am running the website via Cassini in VS2008.
The problem I am seeing every now and then is an error generated from within LinqToSql
data cannot be read, there is already a reader open or
cannot load data into a data table as the data already exists (I do not have the exact exceptions to hand at present but both are internal to LinqToSql).
If the error happens in ControllerOne then ControllerTwo will also fail with a similar error, as if the two requests are running with shared objects.
It doesn't error all the time but it's enough to make me concerned about my architecture and that it's configured wrong in some way.
Is there any way StructureMap could be returning the same instance of ControllerOne and ControllerTwo on subsequent requests, or if it's caching the DBContext in any way? Even though I am not asking it to?
Has anyone seen anything similar when working within Visual Studio/Cassini? Does going through IIS help?
Should I removed LinqToSql?
关闭Visual Studio并再次打开通常可以解决问题一段时间.
非常感谢,如果有人能够解决这个问题.
编辑:包括来自NLog日志文件的日志片段(线程ID是半冒号前的数字):
03/20/2009 01:40:32 12: controller=Timesheet,date=2001-05-06,Action=WeekEnding /beta/Timesheet/2001-05-06?_dc=1237513232397 03/20/2009 01:40:32 10: controller=Timesheet,date=2001-05-06,Action=WeekEnding /beta/Timesheet/2001-05-06?_dc=1237513232449 03/20/2009 01:40:32 10: There is already an open DataReader associated with this Command which must be closed first. System.InvalidOperationException[br] at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader() at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector) at HCD.Intranet.Core.Data.Linq.LinqEmployeeRepository.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding, Int32 nonProjectId) at HCD.Intranet.Core.Services.Impl.EmployeeService.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding) at HCD.Intranet.Core.Models.Timesheet.CalculateHolidaysRemaining() at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteTimesheet(JsonWriter writer, Timesheet timesheet) at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteJson(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonMemberMapping memberMapping) at Newtonsoft.Json.JsonSerializer.SerializeObject(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value) at HCD.Intranet.Core.Web.Mvc.NewtonsoftJsonResult.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.b__e() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 03/20/2009 01:40:32 12: Invalid attempt to call Read when reader is closed. System.InvalidOperationException[br] at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector) at HCD.Intranet.Core.Data.Linq.LinqEmployeeRepository.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding, Int32 nonProjectId) at HCD.Intranet.Core.Services.Impl.EmployeeService.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding) at HCD.Intranet.Core.Models.Timesheet.CalculateHolidaysRemaining() at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteTimesheet(JsonWriter writer, Timesheet timesheet) at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteJson(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonMemberMapping memberMapping) at Newtonsoft.Json.JsonSerializer.SerializeObject(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value) at HCD.Intranet.Core.Web.Mvc.NewtonsoftJsonResult.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11. b__e() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 03/20/2009 01:41:58 12: controller=Timesheet,month=6,year=2001,Action=Calendar /beta/Timesheet/Calendar/6/2001?_dc=1237513318470 03/20/2009 01:41:59 10: controller=Timesheet,date=2001-06-03,Action=WeekEnding /beta/Timesheet/2001-06-03?_dc=1237513318509 03/20/2009 01:41:59 12: The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type. System.InvalidOperationException[br] at Read_TimesheetEntry(ObjectMaterializer`1 ) at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at HCD.Intranet.Core.Data.Linq.LinqTimesheetRepository.GetEntries(Int32 timesheetHeaderId) at HCD.Intranet.Core.Services.Impl.TimesheetService.GetEntries(Int32 timesheetHeaderId) at HCD.Intranet.Core.Models.Timesheet.get_InnerEntries() at HCD.Intranet.Core.Models.TimeMap..ctor(Timesheet timesheet) at HCD.Intranet.Core.Models.Json.TimesheetCalendarJsonConverter.WriteTimesheet(JsonWriter writer, Timesheet[] timesheets) at HCD.Intranet.Core.Models.Json.TimesheetCalendarJsonConverter.WriteJson(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value) at HCD.Intranet.Core.Web.Mvc.NewtonsoftJsonResult.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11. b__e() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 03/20/2009 01:41:59 12: controller=Timesheet,date=2001-06-03,Action=WeekEnding /beta/Timesheet/2001-06-03?_dc=1237513318545 03/20/2009 01:41:59 12: There is already an open DataReader associated with this Command which must be closed first. System.InvalidOperationException[br] at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader() at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector) at HCD.Intranet.Core.Data.Linq.LinqEmployeeRepository.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding, Int32 nonProjectId) at HCD.Intranet.Core.Services.Impl.EmployeeService.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding) at HCD.Intranet.Core.Models.Timesheet.CalculateHolidaysRemaining() at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteTimesheet(JsonWriter writer, Timesheet timesheet) at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteJson(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonMemberMapping memberMapping) at Newtonsoft.Json.JsonSerializer.SerializeObject(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value) at HCD.Intranet.Core.Web.Mvc.NewtonsoftJsonResult.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11. b__e() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 03/20/2009 01:41:59 10: Invalid attempt to call Read when reader is closed. System.InvalidOperationException[br] at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector) at HCD.Intranet.Core.Data.Linq.LinqEmployeeRepository.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding, Int32 nonProjectId) at HCD.Intranet.Core.Services.Impl.EmployeeService.CalculateHolidaysRemaining(Employee employee, DateTime weekEnding) at HCD.Intranet.Core.Models.Timesheet.CalculateHolidaysRemaining() at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteTimesheet(JsonWriter writer, Timesheet timesheet) at HCD.Intranet.Core.Models.Json.TimesheetJsonConverter.WriteJson(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonMemberMapping memberMapping) at Newtonsoft.Json.JsonSerializer.SerializeObject(JsonWriter writer, Object value) at Newtonsoft.Json.JsonSerializer.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter) at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value) at HCD.Intranet.Core.Web.Mvc.NewtonsoftJsonResult.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11. b__e() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13. b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
小智.. 6
我正在和Jeremy Miller讨论这个问题,你不想用SM来管理数据库上下文的生命周期 - 让repo根据需要实例化.此呈现你会怎么做对象更新/持久性(如果你依靠上下文有多个请求,活着)问题,但它是值得的,不是靠这对于一个web应用程序.
我不得不从店面中删除db上下文管理的东西,原因是这样的 - 我得到了内存泄漏.我不会说这是SM的错 - 但总的来说只是让回购开启一个新的背景.
我正在和Jeremy Miller讨论这个问题,你不想用SM来管理数据库上下文的生命周期 - 让repo根据需要实例化.此呈现你会怎么做对象更新/持久性(如果你依靠上下文有多个请求,活着)问题,但它是值得的,不是靠这对于一个web应用程序.
我不得不从店面中删除db上下文管理的东西,原因是这样的 - 我得到了内存泄漏.我不会说这是SM的错 - 但总的来说只是让回购开启一个新的背景.