Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
EF LINQ WHERE C#-Funktion verwenden
seeba
myCSharp.de - Member



Dabei seit:
Beiträge: 76

Themenstarter:

EF LINQ WHERE C#-Funktion verwenden

beantworten | zitieren | melden

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!
private Nachricht | Beiträge des Benutzers
[email protected]
myCSharp.de - Member



Dabei seit:
Beiträge: 407

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
seeba
myCSharp.de - Member



Dabei seit:
Beiträge: 76

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7559
Herkunft: Waidring

beantworten | zitieren | melden

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!"
private Nachricht | Beiträge des Benutzers
seeba
myCSharp.de - Member



Dabei seit:
Beiträge: 76

Themenstarter:

beantworten | zitieren | melden

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?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von seeba am .
private Nachricht | Beiträge des Benutzers
Florian Reischl
myCSharp.de - Experte

Avatar #avatar-2880.jpg


Dabei seit:
Beiträge: 1596
Herkunft: München

beantworten | zitieren | melden

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ß.
private Nachricht | Beiträge des Benutzers
Mr. Bart Simpson
myCSharp.de - Member

Avatar #avatar-3273.gif


Dabei seit:
Beiträge: 502
Herkunft: Mittelfranken

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers