4

コードファーストアプローチでファイルを共有するための小さなMVC4Webサイトを構築しました。ファイルは私のデータベースに次のように保存されます

public byte[] Content { get; set; }

設定しました

<security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="536870912" />
  </requestFiltering>
</security>

<httpRuntime targetFramework="4.5" executionTimeout="6000" maxRequestLength="524288"/>

ファイルサイズを500Mbに制限して、ファイルが実際に私のコードに組み込まれるようにします(最初はこれに少し固執していました)。

実際の問題は、ファイルを受け取ってデータベースに保存しようとしたときに発生します。次のように呼び出します。

DbContext.SaveChanges()

そして、このエラーが発生します:

タイプ'System.OutOfMemoryException'の例外がSystem.Data.Entity.dllで発生しましたが、ユーザーコードでは処理されませんでした

これは、データベースのbyte []に​​格納できるデータの量(またはプロセスで使用できるメモリの量)として、ある種の制限に達しているためだと思います。小さいファイルをアップロードすると、すべてが機能します。

データベースサーバーはSQL2008R2標準サーバーです。

簡単にするために、ファイルをディスクに保存することは避けたいと思います。私のオプションは何ですか?

編集:ファイルを挿入するためにまっすぐな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未満の小さなファイルでは機能しますが、200Mbのファイルではクラッシュします。

以下の回答のコメントに従って、質問にスタックトレースを追加します。

System.OutOfMemoryExceptionは、ユーザーコード
HResult=-2147024882によって処理されませんでした。Message=タイプ'System.OutOfMemoryException'の例外がスローされました。Source = mscorlib
StackTrace:System.Object.MemberwiseClone()at System.Array.Clone()at System.Data.Common.CommandTrees.DbConstantExpression..ctor(TypeUsage resultType、Object value)atSystem.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、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__711.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 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, IDictionary2 parameters)at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext、ActionDescriptor actionDescriptor、IDictionary 2 parameters) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass81.b__7(IAsyncResult )at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)atSystem.Web.Mvc.Async.AsyncControllerActionInvoker。<> c_DisplayClass37。< > c_ DisplayClass39.b _33()atSystem.Web.Mvc.Async.AsyncControllerActionInvoker。<>c_ DisplayClass4f.b _49()InnerException:

解決:

これがどのように解決されたかの完全な例を次に示します。

http://www.syntaxwarriors.com/2013/stream-varbinary-data-to-and-from-mssql-using-csharp/

4

2 に答える 2

8

OutOfMemoryフレームワークやデータベースとは何の関係もありません。これは、要求されたときに CLR がオブジェクトを割り当てることができなかったことを意味します。

おそらく、データを複数のバッファに格納しています。たとえば、HttpPostedFileに 1 つ、 in-memorybyte[]に 1 つ、EF に 1 つなどです。これにより、必要なメモリ量が倍増します。

ASP.NET からのストリーミング読み取りと ADO.NET へのストリーミング書き込みに切り替えます。チュートリアルが利用可能です。「SQL Server UPDATE WRITE」を検索します

于 2013-01-26T23:40:21.607 に答える
2

Entity Framework をバイパスして、ADO.Net (System.Data.SqlClient.SqlCommandなど) を直接使用してみてください。

于 2013-01-26T22:20:33.583 に答える