Die Speicherung von großen Dateien in der Datenbank führt zu Einer Ausnahme des Typs 'System.OutOfMemoryException'
Habe ich eine kleine gebaut, MVC4 Webseite für den Austausch von Dateien mit den code-first-Ansatz. Die Dateien gespeichert sind, in meine Datenbank als
public byte[] Content { get; set; }
Ive set
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="536870912" />
</requestFiltering>
</security>
und
<httpRuntime targetFramework="4.5" executionTimeout="6000" maxRequestLength="524288"/>
Begrenzen die Dateigröße auf 500 Mb, so dass die Datei eigentlich macht es in meinen code (war fest auf dieses eine bit zuerst).
Ist das eigentliche problem passiert, wenn ich die Datei erhalten haben und versuchen, in der Datenbank speichern, ich nenne das:
DbContext.SaveChanges()
Und bekomme diese Fehlermeldung:
Eine Ausnahme des Typs " System.OutOfMemoryException " ist in
System.Data.Entity.dll wurde aber nicht behandelt werden, in Benutzer-code
Ich vermute, das ist weil ich bin zu schlagen, eine Art von limit, wie viele Daten können gespeichert werden, in ein byte[] in die DB (oder wie viel Speicher mein Prozess verwenden darf).. Alles funktioniert beim Upload kleiner Dateien.
Den Datenbank-server ist ein SQL 2008 R2 Standard server.
Ich würde es vorziehen, zu vermeiden, speichern Sie die Dateien auf der Festplatte aus Gründen der Einfachheit.. was sind meine Möglichkeiten?
EDIT: Mit dem Vorschlag zu tun, eine straight-up-SQL-Abfrage, um die Datei einfügen, hab mir letzten das erste problem, bekommen Sie die Datei in die Datenbank:
DbContext.Database.ExecuteSqlCommand(
@"UPDATE FileContents
SET Content = @data
WHERE ID = @id",
new SqlParameter("id", content.ID), new SqlParameter("data", bytearray));
Aber ich bin jetzt immer der exakt gleiche Fehler beim Versuch, die Datei aus der Datenbank statt. Dies bewirkt, dass die Fehlermeldung jetzt:
byte[] respdata = DbContext.Database.SqlQuery<Byte[]>
("SELECT TOP 1 Content FROM FileContents WHERE ID = @id",
new SqlParameter("id", filepost.File.ID)).Single();
Wieder, es funktioniert für kleinere Dateien <100 MB, aber Absturz auf 200 Mb-Dateien.
Hinzufügen stacktrace zu Frage pro Kommentar in den Antworten unten:
System.OutOfMemoryException wurde unhandled by user code
HResult=-2147024882 Meldung=Exception-Typ
'System.OutOfMemoryException " wurde ausgelöst. Source= "mscorlib"
StackTrace:
System.Objekt.MemberwiseClone()
System.Array.Clone () -
System.Daten.Common.CommandTrees.DbConstantExpression..ctor(TypeUsage
resultType, Object Wert)
System.Daten.Mapping.Update.Intern.UpdateCompiler.GenerateValueExpression(EdmProperty
Eigenschaft, PropagatorResult Wert)
System.Daten.Mapping.Update.Intern.UpdateCompiler.BuildSetClauses(DbExpressionBinding
Ziel PropagatorResult Zeile, PropagatorResult originalRow,
TableChangeProcessor Prozessor, Boolean insertMode, Wörterbuch2&
1.MoveNext()
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
System.Daten.Mapping.Update.Intern.UpdateCommandOrderer..ctor(IEnumerable1
2 Parameter)
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
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext
controllerContext, ActionDescriptor actionDescriptor, IDictionary2
1.b__7(IAsyncResult
parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8
)
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Ende()
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult
asyncResult)
bei System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c_DisplayClass37.<>c_DisplayClass39.b_33()
System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c_DisplayClass4f.b_49()
InnerException:
Lösung:
Hier ist ein komplettes Beispiel, wie dies gelöst wurde:
http://www.syntaxwarriors.com/2013/stream-varbinary-data-to-and-from-mssql-using-csharp/
- blogs.msdn.com/b/ericlippert/archive/2009/06/08/...
- Wie sieht Ihre entity-Klasse Aussehen wird und was ist der Datentyp des Felds in der sql server-Tabelle?
- Was ist Ihre aktuelle code Aussehen..? könnten Sie möglicherweise einen Speicherverlust in den vorhandenen code..?
- Der Datentyp in der Datenbank ist vom Datentyp varbinary(max), ich habe es definiert als byte[] in meinem Modell. DJKRAZE bezweifle ich, es ist ein Speicher-Leck, wie es geschieht bei der ersten Anforderung nach dem Start des Projektes, große Dateien immer wieder der Fehler oben
- Haben Sie überprüft, die Maschine, die Speicherauslastung, wenn der Fehler Auftritt?
- 4 von 8 GB frei, wenn die Fehlermeldung Auftritt,
Du musst angemeldet sein, um einen Kommentar abzugeben.
OutOfMemory
hat nichts zu tun mit irgendwelchen Rahmen oder Datenbank. Es bedeutet, dass die CLR konnte nicht alloziert ein Objekt, wenn du dazu aufgefordert wirst.Wahrscheinlich, Sie haben die Daten in mehrere Puffer wie in einem
HttpPostedFile
eine in eine in-memory -byte[]
man in EF, ... multipliziert, die Menge von Speicher benötigt.Schalter streaming liest aus ASP.NET und streaming schreibt ADO.NET. Tutorials sind verfügbar. Suche nach "SQL Server-UPDATE-SCHREIBEN"
(1024 * 1024 * 4).RoundUpToMultiple(8040)
. Viel schneller. (Und CopyTo ohne async als Ihre Write-Methode nicht unterstützt async).Könnten Sie versuchen, unter Umgehung des Entity Framework und mit ADO.Net (
System.Data.SqlClient.SqlCommand
usw.) direkt.