Vorkompilierte Abfragen
Vorkompilierten Abfragen sind schneller, weil der Expression-Tree nur einmal vom Compiler erstellt werden muss. Falls Sie nur lesend auf die Daten zugreifen möchten, dann präferieren Sie "new" in der Select-Anweisung anstelle der Materialisierung ganzer Entity-Objekte.
Datensätze hinzufügen
Neue Entity-Objekte erzeugen Sie mit der statischen Methode "NewACObject()", die jede Entity-Klasse im iPlus-Framework bereitstellen sollte. Dadurch werden alle Eigenschaften initialisiert und mit Standard-Werten belegt, die in der Entwicklungsumgebung eingestellt worden sind. Rufen Sie danach die AddObject-Methode auf, um das neue Objekt der Änderungsnachverfolgung bekannt zu geben. Zum Speichern rufen Sie ACSaveChanges() auf anstatt der gewohnten SaveChanges()-Methode. ACSaveChanges() validiert zuvor alle geänderten Objekte gegenüber den eingestellten Min/Max-Werten. Ist die Validierung oder der anschließende Speichervorgang fehlgeschlagen, erhalten Sie ein Msg-Objekt mit Fehlerinformation und Schweregrad zurück. Mit ACUndoChanges() machen Sie Ihre Änderungen rückgängig. Dies ist bei Langzeitkontexten notwendig, damit nicht jedes Mal mit erneutem Aufruf von ACSaveChanges() die vergangenen Fehler den Speichervorgang für die neuen Änderungen verhindern.
Optimierte Abfragen und Löschen
Verwenden Sie die Include()-Erweiterungsmethode, um mit einer Abfrage weitere in Beziehung stehende Entity-Objekte zu laden. Im nachfolgenden Beispiel muss Entity-Framework kein Lazy-Loading durchführen, sobald auf die Eigenschaft MDMaterialGroup zugegriffen wird:
Ein Löschvorgang wird mit DeleteACObject() durchgeführt. Der zweite Parameter gibt an, ob Validierungen auf Client-Seite durchgeführt werden sollen (z.B. wegen referentieller Integrität). Der dritte Parameter gibt an, ob der Datensatz physikalisch in der Datenbank gelöscht werden soll oder nur stattdessen ein Löschkennzeichen gesetzt wird. Im Beispiel wird zuerst versucht physikalisch zu löschen und im Fehlerfall ein Soft-Delete.
Abfragen auf dem globalen Datenbankkontext (1)
Verwenden Sie diesen Kontext nur dann, wenn Sie Informationen von Typsystem benötigen (Infos über Klassen, Eigenschaften, Methoden, XAMLDesigns...). Bitte beachten Sie, dass Langzeitkontexte immer threadsafe abgefragt werden müssen, weil Sie nie wissen können, ob zeitgleich eine andere Abfrage in einem anderen Thread durchgeführt wird. Verwenden Sie dafür die ACMonitor-Klasse und übergeben das Sperrobjekt "QueryLock_1X000", das wegen der IACEntityObjectContext-schnittstelle jede EF-Kontext-Klasse bereitstellen muss:
Grundsätzlich ziehen Sie bitte "using() mit einem eigenen Kontext" vor, weil damit die Threadproblematik umgangen und der Speicher danach wieder freigeben wird.
Arbeiten mit Datenbank-Queues (2), (3)
Jegliche Abfragen und Änderungen an Entity-Objekten müssen bei Datenbankkontexten die einer Queue angehören, in eine anonyme Methode eingebaut und als delegat der Add()- oder ProcessAction()-Methode übergeben werden:
Weil die Add()- und ProcessAction()-Methode intern selbst eine Threadsperre mittels QueryLock_1X000 durchführt, müssen Sie dies als Anwendungsprogrammierer nicht mehr tun.
Langzeit-Datenbankkontexte
Falls aus technischen Gründen ein Langzeitkontext benötigt wird, dann instantiieren Sie den Kontext mittels dem ACObjectContextManager. Halten Sie die Referenz zu dem neuen Kontext in einem privaten Feld und geben ihn in der überschriebenen Eigenschaft "public override IACEntityObjectContext Database
" zurück. Alle Kind-Instanzen, die auf Ihre Database-Eigenschaft zugreifen erhalten diesen Kontext zurück, weil in der Basisimplementierung immer der Kontext der ParentACComponent zurückgegeben wird. Wenn keine Klasse die Database-Eigenschaft überschreibt, dann erhalten Sie den Datenbankontext der root-Instanz zurück. In einer Anwendung ist es immer der AnwendungsManager (Klasse "gip.core.autocomponent.ApplicationManager"), der "RootDbOpQueue.AppContext (3)" zurückgibt. Wenn der Langzeitkontext nicht mehr benötigt wird, dann entfernen sie ihn vom ACObjectContextManager mittels "DisposeAndRemove()".