Ich schreibe Code, der große Mengen von Bilddaten durchläuft, und bereite einen großen Delta-Block vor, der alles zum Senden komprimiert enthält.
Hier ist ein Beispiel, wie diese Daten sein könnten
[MessagePackObject]
public class Blob : VersionEntity
{
[Key(2)]
public Guid Id { get; set; }
[Key(3)]
public DateTime CreatedAt { get; set; }
[Key(4)]
public string Mediatype { get; set; }
[Key(5)]
public string Filename { get; set; }
[Key(6)]
public string Comment { get; set; }
[Key(7)]
public byte[] Data { get; set; }
[Key(8)]
public bool IsTemporarySmall { get; set; }
}
public class BlobDbContext : DbContext
{
public DbSet<Blob> Blob { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blob>().HasKey(o => o.Id);
}
}
Wenn ich damit arbeite, verarbeite ich alles zu einem Dateistream und möchte zu einem bestimmten Zeitpunkt so wenig wie möglich im Speicher behalten.
Ist es genug, um es so zu machen?
foreach(var b in context.Where(o => somefilters).AsNoTracking())
MessagePackSerializer.Serialize(stream, b);
Füllt dies immer noch den Speicher mit allen Blob-Datensätzen oder werden sie einzeln verarbeitet, während ich den Enumerator durchlaufe. Es wird keine ToList verwendet, nur der Enumerator, daher sollte Entity Framework in der Lage sein, sie unterwegs zu verarbeiten, aber ich bin mir nicht sicher, ob dies der Fall ist.
Alle Entity Framework-Experten hier, die eine Anleitung geben können, wie dies richtig gehandhabt wird.
stream
das?). Schließlich erfordert der schnelle Umgang mit SQL Server-Dateistreamdaten und das Streaming einen anderen Ansatz, der über EF hinausgeht.Antworten:
Wenn Sie einen LINQ-Filter für eine Entität erstellen, ist dies im Allgemeinen wie das Schreiben einer SQL-Anweisung in Codeform. Es wird eine zurückgegeben
IQueryable
, die nicht tatsächlich für die Datenbank ausgeführt wurde. Wenn SieIQueryable
mit einemforeach
oder einen AufrufToList()
durchlaufen, wird die SQL ausgeführt und alle Ergebnisse werden zurückgegeben und im Speicher gespeichert.https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/language-reference/query-execution
Während EF möglicherweise nicht die beste Wahl für reine Leistung ist, gibt es eine relativ einfache Möglichkeit, dies zu handhaben, ohne sich über die Speichernutzung Gedanken zu machen:
Folgendes berücksichtigen
Jetzt haben Sie die Blobs gemäß Ihren Anforderungen gefiltert und für die Datenbank ausgeführt, aber nur die ID-Werte im Speicher zurückgegeben.
Dann
Der große Blob sollte für die Speicherbereinigung verfügbar sein, sobald Sie damit fertig sind, und Ihnen sollte nicht der Speicher ausgehen.
Natürlich können Sie die Anzahl der Datensätze in der ID-Liste überprüfen oder der ersten Abfrage Metadaten hinzufügen, um zu entscheiden, wie sie verarbeitet werden sollen, wenn Sie die Idee verfeinern möchten.
quelle
Id
hat einen Clustered-Index, ist der Leistungstreffer vieler sequentieller Abfragen möglicherweise nicht so schlecht, wie Sie denken.