Laden...

EF LINQ WHERE C#-Funktion verwenden

Erstellt von seeba vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.153 Views
S
seeba Themenstarter:in
74 Beiträge seit 2005
vor 12 Jahren
EF LINQ WHERE C#-Funktion verwenden

verwendetes Datenbanksystem: SQL Server 2008 R2 SP1

Hallo,
ich habe eine Tabelle mit Prozessdaten, die zyklisch aus der Produktion kommen (derzeit ca. 7 Milliarden Zeilen, ~330GB, bei Produktion täglich ca. +1GB).
Diese Daten laufen zwangsweise in die selbe Tabelle.
Nun zeige ich diese Daten in verschiedenen (gefilterten) Ansichten über eine EntityDataSource in einem GridView (ASP.NET, AutoPaging usw.) an.
Jedem Eintrag ist eine Gruppe zugeordnet. Gruppen sind bei uns die verschiedenen Produktionsbereiche (~40). Jetzt wurde die Anforderung gestellt, dass Hans Müller aus der chemischen Vorbehandlung auch nur die Daten aus der chemischen Vorbehandlung einsehen kann. Das wäre nun noch sehr einfach abzubilden mit einem WHERE Group == "chemVorb". Nun gibt es aber Mitarbeiter die 4, 5 oder sogar 20 der 40 Bereiche einsehen dürfen.

Also habe ich eine Entität für Benutzer in meiner DB erstellt, und eine (Viele)-(Viele)-Zuordnung zu den Gruppen vorgenommen.
Jetzt hatte ich mir vorgestellt in die WHERE Klausel so etwas einzubauen: WHERE UserHasAccessRight(....Username, Prozessdatensatz.Group_ID). Wobei UserHasAccessRight eine in .NET definierte Funktion mit Rückgabe eines bool wäre, welche die Gruppenzugehörigkeit prüft. Das funktioniert natürlich nicht, da sich die Funktion nicht in SQL übersetzen lässt.

Muss ich das ganze nun als Stored Procedure realisieren? Gibt es einen anderen Lösungsweg? Ich könnte mir vorstellen, dass die Performance sehr leiden würde, wenn beim Abrufen von vielen Datensätzen für jeden Datensatz die Zugriffsrechte geprüft werden. Andererseits zeige ich die Datensätze ja nur "gepaget" an.

Über Anregungen wäre ich sehr dankbar.

Viele Grüße!

M
402 Beiträge seit 2005
vor 12 Jahren

Hallo,

mach doch einen (zusätzlichen) Filter für das DataGrid => "Gruppe" (z.b. als Select-Feld) und hier lässt du nur die Gruppen zur Auswahl anzeigen zu der der User Zugriff hat.

Damit kannst du die Daten dann so wie von dir schon angesprochen mit

where Gruppe == "blafasel" abfragen...

lg

S
seeba Themenstarter:in
74 Beiträge seit 2005
vor 12 Jahren

Okay, wäre eine Möglichkeit, aber dann kann ich nicht mehrere Gruppen gleichzeitig anzeigen.
Mir ist gerade eine Idee gekommen. Ich kann die Gruppen_IDs auf die der Nutzer zugreifen darf ja in einem Array zur Verfügung stellen. Kann ich dann in einem LINQ Query sowas wie "WHERE Group_ID ''part of'' array" einfügen? Das wäre sicherlich performanter als dies für jeden Eintrag zu prüfen.

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo seeba,

ein WHERE Group_ID IN (...) wäre eine SQL-Lösung die in Linq mittels


IQueryable<T> query = ...
query.Where(q => groups.Contains(q.Group_ID))

erreicht wird.

Sonst könntest du auch das Where dynamsich mit dem PredicateBuilder zusammenbauen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

S
seeba Themenstarter:in
74 Beiträge seit 2005
vor 12 Jahren

Danke für eure Anregungen.
Ich habe es nun so gelöst:


        protected void Page_Load(object sender, EventArgs e)
        {
            ModelContainer mc = new ModelContainer(ConfigurationManager.ConnectionStrings["ModelContainer"].ToString());
            int[] ids = AccessRightChecker.GetGroupsWithDisplayAccessRight(mc, HttpContext.Current.User.Identity.Name);
            string idsCsv = String.Join(", ", ids);
            EntityDataSource.Where = "it.[Group].ID IN {" + idsCsv + "}";
        }

Gibt es eine charmantere Lösung?

1.564 Beiträge seit 2007
vor 12 Jahren

Hallo seeba

Mit EF würde ich, wie Gü bereits geschrieben hat, mal versuchen ob's mit Contains funktioniert.

Mit native ADO.NET würde ich entweder die CSV-Liste der IDs an eine SP übergeben, serverseitig über eine Split-Methode trennen und in eine Temp-Table schreiben mit der man dann joinen kann; oder direkt mit Table Valued Parameters arbeiten.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

502 Beiträge seit 2004
vor 12 Jahren

Die Lösung via IN-Operator funktioniert, aber bei großen Datenmengen ist die nicht anzuraten. Hast Du die M:N Beziehungen auch in der DB persistiert? Wenn ja, dann sollte sich das über JOINs lösen lassen und dadurch deutlich effizienter ausgeführt werden können.

Bart Simpson

Praxis ist wenn alles funktioniert und keiner weiss warum.
Theorie ist wenn man alles weiss, aber nichts funktioniert.

Bei uns wird Theorie und Praxis vereint: Nichts funktioniert und keiner weiss warum...