Laden...

Pattern gesucht: Get-Properties, die Code enthalten, auf dem SQL-Server ausführen (EF)

Erstellt von Daniel_3_17 vor 10 Jahren Letzter Beitrag vor 10 Jahren 900 Views
D
Daniel_3_17 Themenstarter:in
100 Beiträge seit 2008
vor 10 Jahren
Pattern gesucht: Get-Properties, die Code enthalten, auf dem SQL-Server ausführen (EF)

verwendetes Datenbanksystem: EF 6 / MySql

Hi,

ein Entity hat z. B. folgende Property:

public class Bestellung
{
    public virtual List<Budget> Bestellungsposten { get; set; }
		
	public decimal Gesamtsumme
	{
		get
		{
			return Bestellungsposten.Sum(b => b.BudgetLeft);
		}
	}
}

Folgende Abfrage auf die Datenbank funktioniert natürlich nicht

ctx.Bestellungen.Where(b => b.Gesamtsumme > 100); // kann natürlich nicht auf dem SQL-Server ausgeführt werden.

Klar, man kann diese Filter natürlich auch auf dem Client ausführen. Bei sehr großen Datenmengen ist das jedoch ungünstig.

Daher bin ich gerade auf der Suche nach einer guten Möglichkeit.

Lösungsansätze:

1)

Felder, auf die gefiltert werden müssen, redundant in der Datenbank speichern. Immer wenn relevante Felder geändert wurden, müssen diese aktualisiert werden.
Nachteil: Je nachdem wie verzweigt die Zusammenhänge sind, ist die Gefahr sehr groß, dass der reduntante Wert einfach nicht geändert wird.
Hat einer vergessen den Gesamtsummenaktualisierungsmechanismus anzustoßen, wenn ein Posten geändert wird, ist der Gesamtsummenwert also falsch.

2)

Filter als Expression auslagern. So kann es im Getter und in einem Filter angewendet werden.
Siehe: http://stackoverflow.com/a/7777949/2784484

Vorteil: DRY eingehalten.
Nachteil: Umständlich, nicht wirklich "fließender" Code. Überhaupt bei komplexeren Abfragen möglich?

Wie macht ihr sowas? 😃

Grüße,
Daniel

16.834 Beiträge seit 2008
vor 10 Jahren

Variante 2 wäre der korrekte Weg. Finde ich auch weder umständlich noch, dass es kein fließender Code wäre. Expressions sind hier völlig normal.

Im übrigen ist oben List das Problem, das eine Materialisierung erzwingt.
Bei IQueryable<T> sollte er es auf der DB ausführen (sofern noch keine Materialisierung erfolgt ist).
Aus diesem Grund hat List<T> auch nichts in einem generischen EF-Repository Pattern zu suchen - und als NavigationProperty seh ich es ebenfalls kritisch.

Die Materialisierung hier ist etwas "mächtiges". Das falsche Bedienen kann Dich viel kosten; das korrekte Bedienen viel ersparen.
Und: nicht alles in der DB ist unbedingt schneller.