2009-08-17 12 views
1

Ich schreibe eine Aspx-Anwendung, die 1000 von kleinen Kunden in einer gemeinsamen SQL Server-Datenbank hosten wird. Alle Entitäten werden über Linq-To-Sql erstellt und geladen.Mutli Tenancy Backstop Prüfung auf Linq-to-sql Entity load()

Ersatzschlüssel (Identitätsspalten) werden im gesamten Schema für alle Tabellenbeziehungen verwendet. Daher sollte ich mit einem Root-Kundenobjekt zu exklusiven Datensätzen für einen bestimmten Kunden mit regulären Linq-Abfragen (SQL-Joins) navigieren können).

Aus Sicherheitsgründen ist das Obige jedoch ein bisschen zerbrechlich, deshalb möchte ich eine zusätzliche Schicht von Mietprüfungen als Sicherheits-Backstop hinzufügen. Alle Entitäten in meinem Entitätsmodell verfügen über ein nicht indiziertes int-Feld "TenantId".

Ich suche kritische Kommentare zu dieser Lösung aus einer Performance-Perspektive.

public partial class MyLinqEntity 

    partial void OnLoaded() // linq-to-sql extensibility function 
    { 
    if (this.TennantId != HttpContext.Current.Session["tenantId"]) 
     throw new ApplicationException("Logic error, LINQ query crossed tenantId data      boundary"); 
    } 

    partial void OnCreated() // linq-to-sql extensibility function 
    { 
    this.TennantId = HttpContext.Current.Session["tenantId"]); 
    } 

Antwort

0

Sorry das ist meistens zufällige Gedanken ....

Ich mag nicht alle Objekte abhängig von HttpContext.

Auch ich weiß nicht, ob das Suchen in der Sitzung für jedes Objekt schnell genug ist. Ich denke, dass Sie in Bezug auf die Geschwindigkeit in Ordnung sein werden, da ein Datenbank-Lookup normalerweise viel langsamer ist als alles, was Sie tun.

Ich würde dazu neigen, ein Abhängigkeitsinjektions-Framework zu verwenden, um automatisch ein Objekt zu erstellen, das über einen Sitzungsumfang verfügt, um die Prüfung durchzuführen. Wenn Sie jedoch kein anderes Framework für die Abhängigkeiteninjektion benötigen, ist dies ein Over-Kill.

Da alle Ihre Datenbank-Zeilen mandanten-ID-Spalte haben, hoffe ich, Sie können den Scheck in eine linq-to-sql "Zeile gelesen Callback" verschieben, so dass Sie es nicht in jedes Objekt einfügen müssen. Ich kenne nicht "linq-to-sql", aber ich erwarte, dass Sie in das Abfrageerstellungsframework einhaken und allen Datenbankabfragen ein "where tenanted = xx" hinzufügen könnten.

Wenn in allen Steinbrüchen ein "where tenanted = xx" angegeben ist, kann die Datenbank bei Bedarf vom Kunden partitioniert werden, wodurch "Tabellen-Scans" usw. billiger werden.