Time flies when you're having fun, they say, and it's true . After 6 months of hard work, it's finally done: LLBLGen Pro v1.0.2005.1 is available. This release is a significant milestone, because it includes some key elements, like full inheritance and for example basic support for .NET 2.0.
Let's have a look at some of the new key features:
- Full inheritance support. LLBLGen Pro now supports 3 types of entity inheritance:
- Complete hierarchy mapped onto a single table. In LLBLGen Pro this is called TargetPerEntityHierarchy. This is the inheritance type which is very easy to implement and therefore supported by most O/R mappers.
- Every type in a hierarchy mapped onto its own table, no discriminator column. In LLBLGen Pro this is called TargetPerEntity. This inheritance type is hard to implement, most O/R mappers fall back to option 3.
- Every type in a hierarchy mapped onto its own table, with discriminator column in root type. Similar to option 2, and because LLBLGen Pro doesn't need a discriminator column for option 2, this type is supported but the discriminator column is ignored / not required.
- Compact Framework support, including support for SqlServer CE
- Type conversion technology, map transparently any .NET type on any database type Type converters let you map an entity field of any type onto any database field. LLBLGen Pro will do the conversion transparently for you, behind the scenes. You just work with the entity field type. With this you can for example map a boolean entity field onto a NUMBER(1,0) in Oracle, to have true database generic code, which works with SqlServer and Oracle (SqlServer supports a bit/boolean type, Oracle doesn't). But it doesn't stop there, you can also use this to map a field with type XmlDocument onto a varchar database field. The conversion is done through simple TypeConverter objects which are easy to create yourself and which are used inside the LLBLGen Pro designer to control the types of fields which have a type converter applied.
- New, easy to use, compile-time checked query construction mechanism. Here's an example:
Get all orders which have been shipped 4 days after the orderdate:
// C#, SelfServicing OrderCollection orders = new OrderCollection(); orders.GetMulti(OrderFields.ShippedDate == (OrderFields.OrderDate + 4));
// C#, Adapter EntityCollection orders = new EntityCollection(new OrderEntityFactory()); adapter.FetchEntityCollection(orders, new RelationPredicateBucket(OrderFields.ShippedDate == (OrderFields.OrderDate + 4)));
' VB.NET 2005. SelfServicing Dim orders As New OrderCollection() orders.GetMulti(OrderFields.ShippedDate = (OrderFields.OrderDate + 4))
' VB.NET 2005, Adapter Dim orders As New EntityCollection(New OrderEntityFactory()) adapter.FetchEntityCollection(orders, _ new RelationPredicateBucket(OrderFields.ShippedDate = (OrderFields.OrderDate + 4)))All compile time checked and easy to formulate.
- Map as many entities onto a single table/view
- Polymorphic queries and polymorphic prefetch paths
Say you have an inheritance hierarchy of entities: Employee <- Manager <- BoardMember, and BoardMember has a relation with CompanyCar (m:1) which also is an inheritance hierarchy: CompanyCar <- SportsCar and CompanyCar <- FamilyCar.
Fetching all Employees in a collection, will fetch all Manager entities into objects of type ManagerEntity and all BoardMember entities into objects of type BoardMember. Say you want to load all employees and also for each boardmember the company car they have, and as efficient as possible. This asks for a prefetch path, which allows you to specify which related objects to fetch together with a set of fetched objects. Our code then looks like:
// C#, Adapter PrefetchPath2 path = new PrefetchPath2((int)EntityType.EmployeeEntity); path.Add(BoardMemberEntity.PrefetchPathCompanyCar); EntityCollection employees = new EntityCollection(new EmployeeEntityFactory()); adapter.FetchEntityCollection(employees, null, path);
' VB.NET, Adapter Dim path As New PrefetchPath2(CInt(EntityType.EmployeeEntity)) path.Add(BoardMemberEntity.PrefetchPathCompanyCar) Dim employees As New EntityCollection(new EmployeeEntityFactory()) adapter.FetchEntityCollection(employees, Nothing, path)This not only fetches all employee types in objects of the right types, but also fetches only for the boardmember entities the related company car entity, and because CompanyCar is also a hierarchy, each loaded company car will be loaded into objects of the right type: FamilyCar or SportsCar.
- Support for SqlServer 2005 (no UDT's/UDF's/CTE's) Support for the database types varchar(MAX), varbinary(MAX) and Xml is added as well as creating projects based on SqlServer 2005 catalogs and generating SQL at runtime fully compatible with SqlServer 2005. No support for UserDefinedTypes and UserDefinedFunctions based on CLR types nor support for CTE's. This will be added to LLBLGen Pro v2.0.
- Support for partial classes in .NET 2.0, design time databinding and native .NET 2.0 runtime libraries.
- Much faster/compact serialization for remoting.
This upgrade is, as always, free for our customers. If you want to download the demo, please go to this download mirror, to avoid hammering our server: Solutions Design website (12 MB)
Full list of changes
- All type enums are now public
- Firebird driver is now build against v1.7a of the Firebird.NET provider
- Sqlserver's driver now always reads the @@IDENTITY sequence as well, so users can set entity field sequences to @@IDENTITY instead of SCOPE_IDENTITY() if they want to. This is required for entities mapped onto views and which are used with instead-of triggers. The driver now also signals calling code that the user can select a sequence, so in the designer a user can now select a sequence for a field in an entity, this isn't disabled anymore for projects targeting SqlServer.
- SqlServer driver: support for Xml types in SqlServer 2005
- Oracle drivers using ODP.NET: support for XMLType types in Oracle 9i/10g
- Adapter: Catalog name overwriting at runtime has been reworked. You can now pass in a CatalogNameOverwriteHashtable which contains all the name value pairs and the setting what to use. Internally the DataAccessAdapter uses this setting as well. Name overwriting is now done by the DQE at fieldname construction, not when the fieldpersistenceinfos are retrieved. Wildcard can be used. SQLServer specific
- Structure of DQE's: they're now instance classes, no longer classes with static methods.
- Reworked recursive save pipeline using topology sorting of a directed graph: first queues are constructed, then the save actions are started on these queues. This both gives faster recursive saves, but also keeps the transaction shorter (in time), as it's started later (selfservicing has same starts, adapter starts the transaction later). Originally, the recursive save routine saved the entities while traversing/building the tree.
- UnitOfWork classes now use the new recursive save pipeline elements to construct first queues to process before starting the actions on these queues. When a unitofwork(2) object is serialized, it first determines the real elements to save, which makes serializing unitofwork(2) objects very efficient, as only the elements which will take part of a persistence action are serialized into the UnitOfWork(2) serialized data.
- Adapter: serialization / deserialization of entities is now much faster and the data produced is up to 60% smaller.
- Selfservicing: Multi-entity fetch logic now calls OnFetchComplete() after an entity was succesfully fetched and filled with data. Post-fetch initialization logic should be placed inside a method which overrides OnFetchComplete().
- Inheritance support (3 types of inheritance)
- Multi entity on single target mapping
- Type converter technology for converting values transparently from one .NET type to the other .NET type and vice versa, to be used in Entity/View fields and predicates. For example, it offers the ability to map boolean fields directly on non-boolean/bit types in the database, or for example to map an XmlDocument object onto a string type.
- Ability to not map a field in a table / view to a field in an entity
- Polymorphic query support including filtering on entity type
- Compact framework .NET 1.1 support
- SQL CE support
- Prefetch path fetches in combination with paging
- Adapter: Schema name overwriting settings at runtime for multiple schema name overwrites. You can pass in a SchemaNameOverwriteHashtable which contains the from-to namepairs and the setting what to do. Wildcard can be used. SQLServer, Oracle, DB2 specific.
- MySql: Update entities directly with multi-entity filter has been added.
- FieldBetweenPredicate now also handles field BETWEEN value AND field, field BETWEEN field AND value, field BETWEEN field AND field
- ORMInheritanceInfoException exception, meant for errors determined during query execution, for example when the inheritance info data is out of sync with the data in the db, which occurs for example when the type has to be determined of the row retrieved from the db and the discriminatorvalue is unknown.
- Prefetch path optimization with a user definable threshold when to switch from one method to the other.
- Support for Cross joins.
- Overload to DataAccessAdapter.SaveEntity, which accepts recurse and refetchAfterSave but not a predicate.
- SelfServicing: EntityCollectionBase.DoNotPerformAddIfPresent flag to signal if EntityCollectionBase.Add() should check if the entity to add is already in the collection (default, true) or not (false).
- Adapter: New overloads for FetchTypedList and FetchTypedView which are simpler to use (e.g. accept a typedlist/typed view and don't require you to retrieve the fields info / relations info first.
- EntityCollectionBase(2) now has 2 properties (ConcurrencyPredicateFactoryToUse and EntityValidatorToUse) which will set these properties of any new entity created in a collection fetch to the values stored in these two properties. Also done when AddNew() is called in a databinding scenario.
- OnBeginEdit(), OnEndEdit(), OnCancelEdit(), OnTransactionCommit() and OnTransactionRollback() as protected virtual methods to EntityBase(2).
- Adapter specific constructor to EntityRelation class.
- SqlServer: inserts into a table with solely an identity field are now possible. (INSERT INTO table DEFAULT VALUES)
- Prefetch path optimization through caching of PK hashes.
- UnitOfWork(2) now offer a way to construct the insert/update queues prior to actually committing them. These queues aren't reset after a commit so can be used to fine-grained control over the elements participating in the unitofwork.
- Native .NET 2.0 builds for the ormsupport classes and various DQE's. The ORM support classes build doesn't use ICustomTypeDescriptor on the entity classes, which should enable design time databinding on .NET 2.0 for the time being. (winforms).
- Polymorphic prefetch paths: fetches of supertypes can be performed with prefetch paths which refer to related objects of subtypes and which will load only the subtype's related objects into the subtype instances (if available).
- SortClause.CaseSensitiveCollation. This flag will apply UPPER() (or db specific equivalent) to the field to sort on, to make case sensitive database installations be able to sort case insensitively.
- Adapter: OnBeforeTransactionCommit, OnAfterTransactionCommit, OnBeforeTransactionRollback and OnAfterTransactionRollback added to DataAccessAdapterBase as public virtual methods.
- Adapter: New constructor to RelationPredicateBucket which accepts an IPredicate to ease the construction of filters for Adapter.
- The regular color in the logviewer is now green instead of maroon. Errors are now much easier to spot.
- Custom entity relation editor: the checkbox for auto-detect m:n relations is now only checked if the refresher preference to hide m:n relations automatically is set to false.
- Custom entity relation editor: the name of the field mapped onto the relation to create is now initially set with the name of the related entity.
- Relation nodes of an entity are now sorted ascending in project explorer
- Fields mapped onto relation nodes of an entity are now sorted ascending in project explorer.
- It's now possible to select a sequence for a field which is in an entity mapped onto a view and mark it as identity for sqlserver.
- New preference setting: AddNewFieldsAfterRefresh, which controls if newly found target fields are added as new fields or are added to the list of unmapped fields.
- New preference setting: HideManyToManyRelationsOnCreation, which controls if newly created m:n relations should be marked 'hidden' by default.
- Multiple entities can now be mapped on a single target.
- Entity list viewer for proper overview which entity is mapped onto which target.
- New preference setting: AutoAssignTypeConverterToNewField, which controls if a newly added field (for example in a new entity) gets a matching type converter assigned to it automatically, based on the type conversion definitions defined in the project.
- Plugin which toggles the hide flag on m:n relations. If a relation can't be made unhidden (because one of the two relations it's build on is hidden), it's not marked unhidden.
- Plugin which applies selected Type Conversion Definitions to selected elements, to quickly set type converters on existing projects.
- Option (ManuallySelectRenamedTargetsAfterRefresh) added which will cause the refresher to pop up a dialog (if not unattended) in which the user can select which target to select for a given entity, if the target couldn't be found by the refresher, for example in the case when the target has been renamed.
- Option (LazyLoadingWithoutResultReturnsNew) added to set the flags for the _entityReturnsNewIfNotFound flags in Selfservicing to a value specified in the designer. This makes it easy to set this flag once for all generated entities. Selfservicing specific.
- Context menu to Relations treeview in Entity Editor for easy removal of custom relations and toggle actions on relations.
- Typed list relations can now also have the join hint for a Cross join.
- Typed list designer now has 'Field index' in the column list of the fields in the select list. Use shift-click on the column headers to sort on multiple columns.
- Entities mapped onto views can now have nullable fields.
- Entity hierarchy visualizer.
- Lpt templates can now be bound to templateid's which are included in TDL templates. This greatly enhances the scope of the include templates as with lpt templates (with <% %> syntax and template code in C#/VB.NET) it's possible to access the complete project object graph. This is completely transparent, just bind a .lpt template to a template id which is included in a TDL template and it will be called.
- Two new overloads to ResultsetFields.DefineField() for each typed view, which accept an alias for the field.
- New method in entity classes: TestCurrentFieldValueForNull(index), which returns true if the current value of a field represents null/undefined. This is for example the case for a field of a new entity which hasn't been changed, or a field in a non new entity which hasn't been changed or which has been set to null/Nothing.
- Support for partial classes in VS.NET 2005 scenario's: all classes are generated as partial classes (C#) if a VS.NET 2005 generator scenario is chosen. VB.NET 2005 classes can already be extended with partial classes without having the generated classes defined as 'Partial'.