Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架-OutOfMemory异常_C#_Entity Framework_Silverlight_Out Of Memory - Fatal编程技术网

C# 实体框架-OutOfMemory异常

C# 实体框架-OutOfMemory异常,c#,entity-framework,silverlight,out-of-memory,C#,Entity Framework,Silverlight,Out Of Memory,我正在开发一个Silverlight业务应用程序,并希望实现一个“多部分”上载,它将单个文件拆分为大小为4096KB的部分。为了将这些部分从客户端上传到服务器,我使用了一个WebClient(客户端)和一个通用处理程序(*.ashx,服务器端) 战略: 在第一部分中,将创建实体框架类的新实例。这个对象有一个字段/属性“binary”(在SQL中是varbinary(MAX),在实体框架中是byte[])。我将第一部分存储在属性“binary”中并执行SaveChanges()。然后,处理程序将这

我正在开发一个Silverlight业务应用程序,并希望实现一个“多部分”上载,它将单个文件拆分为大小为4096KB的部分。为了将这些部分从客户端上传到服务器,我使用了一个WebClient(客户端)和一个通用处理程序(*.ashx,服务器端)

战略: 在第一部分中,将创建实体框架类的新实例。这个对象有一个字段/属性“binary”(在SQL中是varbinary(MAX),在实体框架中是byte[])。我将第一部分存储在属性“binary”中并执行SaveChanges()。然后,处理程序将这个新对象的ID(主键)返回给客户端

对服务器的第二个请求除了文件的第二部分之外,还包含第一个请求之后返回的ID。在服务器上,我从数据库加载先前创建的对象并附加第二部分

myobject.binary = myobject.binary.Concat(bytes).ToArray<byte>();
myobject.binary=myobject.binary.Concat(字节).ToArray();
myobject是以前创建的对象,是我要附加到binary属性的部分

我重复这个“策略”,直到整个文件上传到服务器。这适用于最大大小为~78MB的文件。对于大小约为83MB的文件,它可以偶尔工作。大小为~140MB的文件将在SaveChanges()处中止,并出现OutOfMemory异常

堆栈跟踪

at System.Object.MemberwiseClone()
at System.Array.Clone()
at System.Data.Common.CommandTrees.DbConstantExpression..ctor(TypeUsage resultType, Object value)
at System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateValueExpression(EdmProperty property, PropagatorResult value)
at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildSetClauses(DbExpressionBinding target, PropagatorResult row, PropagatorResult originalRow, TableChangeProcessor processor, Boolean insertMode, Dictionary`2& outputIdentifiers, DbExpression& returning, Boolean& rowMustBeTouched)
at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildUpdateCommand(PropagatorResult oldRow, PropagatorResult newRow, TableChangeProcessor processor)
at System.Data.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
at System.Data.Mapping.Update.Internal.UpdateTranslator.<ProduceDynamicCommands>d__0.MoveNext()
at System.Linq.Enumerable.<ConcatIterator>d__71`1.MoveNext()
at System.Data.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable`1 commands, UpdateTranslator translator)
at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at MyObjectContext.SaveChanges(SaveOptions options) in PathToMyEntityModel.cs:Line 83.
at System.Data.Objects.ObjectContext.SaveChanges()
at MultipartUpload.ProcessRequest(HttpContext context) in PathToGenericHandler.ashx.cs:Line 73.
at System.Object.MemberwiseClone()
在System.Array.Clone()处
位于System.Data.Common.CommandTrees.DbConstantExpression..ctor(类型使用结果类型,对象值)
位于System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateValueExpression(EdmProperty属性,PropagatorResult值)
位于System.Data.Mapping.Update.Internal.UpdateCompiler.BuildSetClaires(DbExpressionBinding目标、PropagatorResult行、PropagatorResult原始行、TableChangeProcessor处理器、Boolean insertMode、Dictionary`2和outputIdentifiers、DbExpression和returning、Boolean和RowMustTouched)
位于System.Data.Mapping.Update.Internal.UpdateCompiler.BuildUpdateCommand(PropagatorResult oldRow、PropagatorResult newRow、TableChangeProcessor)
位于System.Data.Mapping.Update.Internal.TableChangeProcessor.CompileCommand(ChangeNode ChangeNode,UpdateCompiler编译器)
在System.Data.Mapping.Update.Internal.UpdateTranslator.d_u0.MoveNext()中
在System.Linq.Enumerable.d_u71`1.MoveNext()中
位于System.Data.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable`1命令,UpdateTranslator转换器)
位于System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()处
位于System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntITYAAdapter适配器)
位于System.Data.EntityClient.EntityAdapter.Update(EntityStateManager entityCache)
位于System.Data.Objects.ObjectContext.SaveChanges(保存选项)
在PathToMyEntityModel.cs中的MyObjectContext.SaveChanges(SaveOptions选项)中:第83行。
位于System.Data.Objects.ObjectContext.SaveChanges()处
在PathToGenericHandler.ashx.cs中的multipartPload.ProcessRequest(HttpContext上下文)处:第73行。
有人知道我的实现有什么问题吗?如果您需要更多信息或代码片段,请告诉我

亲切问候,,
克里斯

想想看。上传(例如)130 MB后,执行此行需要多少内存:

myobject.binary = myobject.binary.Concat(bytes).ToArray<byte>();
myobject.binary=myobject.binary.Concat(字节).ToArray();
显然,前面的数组在内存中,即130MB。不知何故,新的阵列也必须在内存中,那又是130MB,对吗

事实上,情况更糟
Concat()
正在生成一个序列,而
ToArray()
不知道它会有多大

因此,
.ToArray()
所做的是,它创建一个内部缓冲区,并开始用
.Concat()
迭代器的输出填充它。显然,它不知道缓冲区应该有多大,所以每隔一段时间它就会发现输入的字节数超过了它的缓冲区所能容纳的字节数。然后需要创建一个更大的缓冲区。它将要做的是创建一个两倍于前一个缓冲区的缓冲区,复制所有内容并开始使用新的缓冲区。但这意味着在某个时刻,旧的缓冲区和新的缓冲区必须同时在内存中

在某些情况下,旧的缓冲区将是128MB,而新的缓冲区将是256MB。加上130MB的旧文件,这大约是半GB。现在,我们希望没有两个(或更多)用户同时这么做

我建议你使用不同的机制。例如,将上载的Chunck存储在磁盘上的临时文件中。当一个新的chunck出现时,只需附加到文件中。只有在上传完成后,才能对文件执行您必须执行的任何操作,例如,将其存储在数据库中

另外,请注意.NET中数组的最大大小受31位索引的限制。因此,无论系统中有多少RAM,字节数组的最大大小都是2GB


最后:如果您要处理这么大的内存块,请确保您在64位进程中运行,并且至少在.NET4.5上运行,这样您就可以利用。但即便如此,这也不是魔术。

想想看。上传(例如)130 MB后,执行此行需要多少内存:

myobject.binary = myobject.binary.Concat(bytes).ToArray<byte>();
myobject.binary=myobject.binary.Concat(字节).ToArray();
显然,前面的数组在内存中,即130MB。不知何故,新的阵列也必须在内存中,那又是130MB,对吗

事实上,情况更糟
Concat()
正在生成一个序列,而
ToArray()
不知道它会有多大

因此,
.ToArray()
所做的是,它创建一个内部缓冲区,并开始用
.Concat()
迭代器的输出填充它。显然,它不知道缓冲区应该有多大,所以每隔一段时间它就会发现输入的字节数超过了它的缓冲区所能容纳的字节数