背景是使用具有 Repository 和 UnitOfWork 模式的实体框架的 ASP.NET WebForms 应用程序。请注意,该应用程序还配置为使用进程外 StateServer 进行会话管理,我理解这意味着我存储在会话中的任何内容都必须是可序列化的。
我还有一个 HttpModule 配置为在每个 HttpRequest 上创建一个 UnitOfWork 对象(其中包含我的实体上下文对象),将其存储在 HttpContext.Current.Items 中,当然还可以在每个请求结束时处理它。
我的 UnitOfWork 类本身包含我的每个存储库的属性以及实体上下文本身。
为了在未来进行更灵活的测试,我创建了一个 IObjectContext 接口,其中包含实体上下文中的方法和属性的签名,并为我的实体上下文创建了一个分部类并从它继承。
public class UnitOfWork : IUnitOfWork
{
private IObjectContext context;
}
public UnitOfWork(IObjectContext context)
{
this.context = context;
}
public partial class MyEntities : IObjectContext
{
}
private static void ApplicationBeginRequest(Object source, EventArgs e)
{
if (!HttpContext.Current.Items.Contains("UnitOfWork"))
{
IUnitOfWork unitOfWork = new UnitOfWork();
HttpContext.Current.Items.Add("UnitOfWork", unitOfWork);
}
}
private void ApplicationEndRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Items["UnitOfWork"] != null)
((IUnitOfWork)HttpContext.Current.Items["UnitOfWork"]).Dispose();
}
这里的目标最终是允许我伪造我的实体上下文对象以创建例如用于测试目的的内存上下文。
一切都很好,直到我开始在我的实体上下文对象上收到“未标记为可序列化”异常。显然,我的第一个想法是将 [Serializable] 添加到我的部分实体上下文类中,但随后它开始抱怨 Assembly System.Data.Entity 中的 System.Data.Objects.ObjectContext 未标记为可序列化(我显然没有有任何控制权)。
我在这里想念什么?似乎我无法将我的实体上下文对象存储在 HttpContext.Current.Items 中,我必须为我的工作单元模式实现执行此操作。
这是因为我使用的是 ASP.NET 状态服务器而不是进程内会话管理吗?如果您使用状态服务器,那么肯定有一种方法可以在 HTTP 请求的整个生命周期内存储上下文吗?
只是觉得我在这里遗漏了一些明显的东西。我已将 [Serializable] 添加到从 UnitOfWork 到 MyEntities 上下文到每个存储库类的所有内容中。仍然无法超越实体上下文本身。
有任何想法吗?
更新(添加堆栈跟踪):
[SerializationException: Type 'myDAL.Model.myEntities' in Assembly 'myDAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.]
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) +14324629
System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) +408
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() +420
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +532
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) +969
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) +633
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) +322
System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer) +1487
[HttpException (0x80004005): Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.]
System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer) +2485899
System.Web.SessionState.SessionStateItemCollection.WriteValueToStreamWithAssert(Object value, BinaryWriter writer) +49
System.Web.SessionState.SessionStateItemCollection.Serialize(BinaryWriter writer) +746
System.Web.SessionState.SessionStateUtility.Serialize(SessionStateStoreData item, Stream stream) +336
System.Web.SessionState.SessionStateUtility.SerializeStoreData(SessionStateStoreData item, Int32 initialStreamSize, Byte[]& buf, Int32& length, Boolean compressionEnabled) +99
System.Web.SessionState.OutOfProcSessionStateStore.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) +3828904
System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +1021
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165