我已经构建了一个小型MVC4网站,用于使用代码优先方法共享文件。这些文件以
的形式存储在我的数据库中public byte[] Content { get; set; }
我已经设定了
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="536870912" />
</requestFiltering>
</security>
和
<httpRuntime targetFramework="4.5" executionTimeout="6000" maxRequestLength="524288"/>
要将文件大小限制为500 Mb,以便文件实际上将其放入我的代码中(先将其粘贴在此处)。
当我收到文件并尝试将其保存到数据库时,实际问题就出现了,我打电话给:
DbContext.SaveChanges()
并收到此错误:
发生了'System.OutOfMemoryException'类型的异常 System.Data.Entity.dll但未在用户代码中处理
我猜这是因为我在数据库中的byte []中存储了多少数据(或者我的进程允许使用多少内存),因此我遇到了某种限制。一切都在上传时有效较小的文件。
数据库服务器是SQL 2008 R2 Standard服务器。
为了简单起见,我宁愿避免将文件存储在磁盘上。我的选择是什么?
编辑:使用直接SQL查询插入文件的建议让我超越了将文件导入数据库的第一个问题:
DbContext.Database.ExecuteSqlCommand(
@"UPDATE FileContents
SET Content = @data
WHERE ID = @id",
new SqlParameter("id", content.ID), new SqlParameter("data", bytearray));
但是我现在在尝试将文件从数据库中取出时得到完全相同的错误。这会导致错误:
byte[] respdata = DbContext.Database.SqlQuery<Byte[]>
("SELECT TOP 1 Content FROM FileContents WHERE ID = @id",
new SqlParameter("id", filepost.File.ID)).Single();
同样,它适用于较小的文件<100 MB但崩溃的200 Mb文件。
根据以下答案中的评论添加堆栈跟踪问题:
System.OutOfMemoryException未被用户代码
处理 HResult = -2147024882消息=类型异常 抛出'System.OutOfMemoryException'。来源= mscorlib程序
堆栈跟踪: 在System.Object.MemberwiseClone() 在System.Array.Clone() 在System.Data.Common.CommandTrees.DbConstantExpression..ctor(TypeUsage resultType,Object value) 在System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateValueExpression(EdmProperty) property,PropagatorResult值) 在System.Data.Mapping.Update.Internal.UpdateCompiler.BuildSetClauses(DbExpressionBinding) target,PropagatorResult row,PropagatorResult originalRow, TableChangeProcessor处理器,Boolean insertMode,Dictionary2& outputIdentifiers, DbExpression& returning, Boolean& rowMustBeTouched) at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildInsertCommand(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() 在System.Data.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable1 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 System.Data.Entity.Internal.InternalContext.SaveChanges() at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() at System.Data.Entity.DbContext.SaveChanges() at FilePublicator2.Controllers.FileController.Upload(String qqfile) in d:\Projects\FilePublicator2\trunk\FilePublicator2\Controllers\FileController.cs:line 115 at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary
2个参数) 在System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext,ActionDescriptor actionDescriptor,IDictionary2 parameters) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8
1.b__7(IAsyncResult) ) 在System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End() 在System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult) asyncResult) 在System.Web.Mvc.Async.AsyncControllerActionInvoker。&lt;&gt; c _DisplayClass37。&lt;&gt; c_ DisplayClass39.b _33() 在System.Web.Mvc.Async.AsyncControllerActionInvoker。&lt;&gt; c_ DisplayClass4f.b _49() 的InnerException:
解决方案:
以下是如何解决这个问题的完整示例:
http://www.syntaxwarriors.com/2013/stream-varbinary-data-to-and-from-mssql-using-csharp/
答案 0 :(得分:8)
OutOfMemory
与任何框架或数据库无关。这意味着CLR在被要求时无法分配对象。
或许,您将数据存储在多个缓冲区中,例如HttpPostedFile
中的一个,内存中byte[]
中的一个,EF中的一个... ...这会使所需的内存量倍增。
切换到ASP.NET的流式读取和流式写入ADO.NET。教程可用。搜索“SQL Server UPDATE WRITE”
答案 1 :(得分:2)
您可以尝试绕过实体框架并直接使用ADO.Net(System.Data.SqlClient.SqlCommand
等)。