Pre-compiled queries
Pre-compiled queries are faster because the expression tree only has to be created once by the compiler. If you only want to have read access to the data, then prefer "new" in the select statement instead of materializing entire entity objects.
--V5 Version--
In the iPlus V5 version the command for using precompiled queries has changed. Instead of using CompiledQuery.Compile
you use EF.CompileQuery
. It also has some new limitations and in this case the result can't be an IQueryable type as the compiled query delegate cannot be composed further. You also cannot use the entities directly in the compiled query as that cannot be translated. There are also some other limitations as there are some LINQ methods that also cannot be translated.
Add records
You create new entity objects with the static method "NewACObject()", which every entity class should provide in the iPlus framework. This initializes all properties and assigns them with standard values that have been set in the development environment. Then call the AddObject() method to announce the new object to the change tracking. To save, call ACSaveChanges() instead of the usual SaveChanges() method. ACSaveChanges() validates all changed objects against the set min / max values. If the validation or the subsequent saving process has failed, you will receive a Msg object with error information and severity. With ACUndoChanges() you can undo your changes. This is necessary in long-term contexts,
--V5 Version--
In Entity Framework Core, the method for adding objects has been simplified. Instead of using AddObject()
, you can now directly use Add()
. The functionality of adding objects remains consistent.
Optimized queries and deletion
Use the Include() extension method to load other related entity objects with a query. In the following example, the entity framework does not have to perform lazy loading as soon as the MDMaterialGroup property is accessed:
A delete operation is carried out with DeleteACObject(). The second parameter specifies whether validations should be carried out on the client side (e.g. due to referential integrity). The third parameter specifies whether the data record should be physically deleted in the database or whether a deletion indicator is only set instead. In the example, an attempt is first made to physically delete and, in the event of an error, a soft delete.
--V5 Version--
A breaking change in Entity Framework Core and the iPlusV5 framework is that lazy loading has a different behavior and in the example provided where the property mat.MDMaterialGroup.MDMaterialGroupName
is accesssed without lazy loading can't be replicated in the new framework and the property will be lazy loaded because of the new behavior.
Queries on the global database context (1)
Use this context only if you need information from the type system (information about classes, properties, methods, XAMLDesigns ...). Please note that long-term contexts must always be queried thread-safe, because you can never know whether another query is being carried out in another thread at the same time. Use the ACMonitor class for this and pass the lock object "QueryLock_1X000", which, because of the IACEntityObjectContext interface, must provide every EF context class:
Basically, please prefer "using() with its own context" because this avoids the thread problems and the memory will then be released again.
Working with database queues (2), (3)
Any queries and changes to entity objects for database contexts belonging to a queue must be built into an anonymous method and passed as a delegate to the Add() or ProcessAction() method:
Because the Add() and ProcessAction() methods internally lock threads using QueryLock_1X000, you, as an application programmer, no longer have to do this.
Long-term database contexts
If a long-term context is required for technical reasons, then instantiate the context using the ACObjectContextManager. Keep the reference to the new context in a private field and return it in the overridden property "public override IACEntityObjectContext Database
". All child instances that access your Database property get this context back, because the context of the ParentACComponent is always returned in the basic implementation. If no class overwrites the Database property, you get the database context of the root instance. In an application, it is always the ApplicationManager (class "gip.core.autocomponent.ApplicationManager"), the "RootDbOpQueue.AppContext (3)" returns. If the long-term context is no longer required, remove it from the ACObjectContextManager using "DisposeAndRemove()".