Migrating your code
With every release of the runtime libraries, designer and accompanying template sets new features are added and changes are made to fix bugs or design flaws. While we do everything we can to avoid breakage of your code, some changes are unavoidable. This section illustrates some important points to consider when you move your own code using the LLBLGen Pro generated code to the v5.2 templates and updated runtime libraries (version number: 5.2.x).
Before you proceed, please read the following important notice:
Please make backup copies of your work before migrating to v5.2. That is: make backups of your own code and the generated code before using LLBLGen Pro v5.2. This way you can roll back to your original work and continue working with 5.1 or earlier versions if you decide that migration to v5.2 requires more work than you anticipated and you have to complete it at a later date. A good source control system can take care of that.
If you're generating new v5.2 code on top of a project generated with v5.1 or earlier, it can be that when you load the project(s) into VS.NET, the references to the runtime libraries are still pointing to the v5.1 runtime libraries or earlier versions. Please make sure you manually update these references to the v5.2 runtime libraries, and, if applicable, be sure to remove the references to the LinqSupportClasses and QuerySpec assemblies as starting with LLBLGen Pro v4.0, these are now merged into the ORMSupportClasses assembly.
See for more details about referencing the runtime libraries the section Compiling your code.
Furthermore, it's key to regenerate the code and also to check if you're indeed referencing the proper runtime libraries.
Below are the list of breaking changes in every 2.x version, v3.0, v3.1, 3.5, 4.0, 4.1, 4.2, 5.0, 5.1 as well as the current version, v5.2. If you're migrating from version X to v5.2, be sure you read all the breaking changes on this page starting with the version following X up till v5.1 included. If you run into a breaking change which isn't enlisted here, please let us know so we can add it here.
Migrating generated code from v5.1 to v5.2
The following changes are breaking changes introduced by v5.2. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v5.2
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v5.2. They're all of low impact.
- All
ApplicationException
throws have been converted toInvalidOperationException
throws. - All
ORMException
classes are now derived fromSystem.Exception
, and no longer fromApplicationException
. IComPlusAdapterContext
has been removed as its implementation has been removed for quite some time. The interface should have been removed a long time ago. Using this interface was of no use in your code as Com+ support has been removed from the runtime for some time already so it's highly unlikely you run into this.
Migrating generated code from v5.0 to v5.1
The following changes are breaking changes introduced by v5.1. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v5.1
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v5.1
-
The interface member
IDbSpecificHintCreator.CreateHintStatement
has been marked obsolete and is no longer usable. Please use the FromClauseDirective system instead. This breaking change is likely not impacting anyone, only the people who modified the runtime to add their own table hints. To move to the new FromClauseDirective system, please see the sourcecode of the SQL Server query engine how hints are created in v5.1 onwards. - QuerySpec: the extension method
DynamicQuery<T>.Select(fields)
is now marked as obsolete with error trigger, as calling the method on aDynamicQuery<T>
is not allowed, the overload shouldn't be in the API as calling the method on aDynamicQuery<T>
would overwrite the projection of the query but not the projection lambda. Calling this method is highly likely a mistake in the situation where the user wants to wrap theDynamicQuery<T>
with another select. The obsolete message suggests that now. It's not likely you run into this in your code as in earlier versions the method didn't work properly.
Migrating generated code from v4.2 to v5.0
The following changes are breaking changes introduced by v5.0. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v5.0
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v5.0
- No more support for RIA Services. Microsoft has stopped supporting this framework, which has been abandoned within Microsoft since it's first release, and we do too. If you want to keep using RIA services with v5, you have to manually migrate the v4.x RIA support classes to v5 and compile the sourcecode manually against the v5 ORM Support Classes. You can obtain the v4.x RIA services support classes sourcecode from the LLBLGen Pro website's My Account section, v4.2 sourcecode archive under 'Extras' in the v4.2 section.
- No more support for Sybase iAnywhere (ASA) and Sybase Adaptive Server Enterprise (ASE). The Sybase ASA/ASE DQEs are published on GitHub for the users coming from older LLBLGen Pro versions but they're not supported anymore. Sybase ASE code repository on GitHub | Sybase ASA code repository on GitHub
- No more DebuggerVisualizers for VS.NET 2008. The Visualizers are no longer supported on VS.NET 2008, we only support VS.NET 2010 and upwards.
IGeneralDataProjector
interface now has a new property RequiresNewObjectArrayPerRow.If you implement your ownIGeneralDataProjector
deriving classes, you have to implement this property as well. The property signals the projection engine whether a newobject[]
array has to be allocated with each row. Return true from this property if your projector caches the passed inobject[]
. Return false if you copy values from theobject[]
passed in but don't cache it / wrap it in your projector.-
String uniquing/caching in Adapter and SelfServicing has been removed. If you set StringCacheForFetcher properties to a value or to a
UniqueList<string>
cache in your code, you can safely remove those statements. The main reasons for removing this feature are the following:- It actually doesn't save memory: the string read from the datareader is already allocated. If the string cache already contained the string, the cached instance was used, however the already allocated string still occupied memory, which would still need to be garbage collected. So till the next GC.Collect run, this memory was still being allocated, even if string caching was used or not. GC Collect runs in the CLR aren't run often if there's no memory pressure, sometimes it takes longer than 15 minutes or more. With the GC hit still in place, it would only give less memory to be allocated at a given moment by a set of entities or fetched objects if the objects live beyond a GC collect cycle. For these long-lived sets, it's however better to use resultset caching which give faster queries and as they re-use all values fetched, don't re-allocate strings.
In the general usage of fetching objects, using them, then discarding them, it is highly likely the objects don't live longer than the next time to the GC collect, making the optimization actually not an optimization but a a degration to performance. - Uniquing the strings using the
UniqueList<string>
(still the fastest way to do this) was rather slow: it caused a 20% or more performance hit.
- It actually doesn't save memory: the string read from the datareader is already allocated. If the string cache already contained the string, the cached instance was used, however the already allocated string still occupied memory, which would still need to be garbage collected. So till the next GC.Collect run, this memory was still being allocated, even if string caching was used or not. GC Collect runs in the CLR aren't run often if there's no memory pressure, sometimes it takes longer than 15 minutes or more. With the GC hit still in place, it would only give less memory to be allocated at a given moment by a set of entities or fetched objects if the objects live beyond a GC collect cycle. For these long-lived sets, it's however better to use resultset caching which give faster queries and as they re-use all values fetched, don't re-allocate strings.
IDbSpecificGenerator.CreateLikeParameter(string pattern)
has been removed; all code should use the overload which accepts the field type.- OData Support Services are now built against 5.7.0.0 of the Microsoft OData Services v1-3.
- Replacing an entity E1 in a collection C with an entity E2 will now place E1 into the removal tracker collection of C if E1 and E2 have different PK values.
Migrating generated code from v4.1 to v4.2
The following changes are breaking changes introduced by v4.2. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v4.2
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v4.2.
- A unit of work will now report the actually deleted entities more precisely. If an entity was denied to be deleted, it no longer is included in the amount of entities deleted.
- The SelfServicing DaoBase class' ctor now requires an instance to the persistenceinfoprovider class. This is normally provided by the generated CommonDaoBase class. In case you use a custom CommonDaoBase class template, you have to adjust your template accordingly. See the CommonDaoBase template ctor call how to do that.
- IResultsetCache has been updated with additional methods to implement new features. If you implement this interface, you have to implement the additional new methods as well. See the ResultsetCache class in the ORM Support Classes for details how to do that.
- By default the allowed action combination for entities mapped onto views is 'Retrieve'. This means that saving an entity mapped onto a view by default results in a no-op. If you use triggers to make a save onto a view work, be sure to set in the designer the allowed action combination for these entities to a variant which allows insert / update and if necessary, delete. You can detect the action being denied by enabling the ORMPersistenceExecution tracer at level 3 (Info).
- Adapter specific: The two-class scenario for Adapter has been deprecated and it's not recommended you use it anymore as no new features introduced in v4.2 have been added to the specific templates for this scenario. Instead use partial classes. The preset is still available, if you need to upgrade to v4, however it's highly recommended you refactor your code to move to partial classes and use the General preset instead for adapter. The code generated with the Two-class scenario preset for Adapter will work, however won't contain Tvf calls for Linq nor does it support Linq queries / query spec queries for e.g. typed lists. The preset is in a separate folder 'Deprecated'. The templates are also moved to a Deprecated folder. The templates are now found in a deprecated templatebindings file, and it's not recommended to use these templates.
- OData support classes: The OData Support Classes are now built against WCF Data Services server v5.6.1 (was v5.6.0). If you need OData v4 support, you manually have to compile the OData Support Classes against the v6.x assembly on nuget.
Migrating generated code from v4.0 to v4.1
The following changes are breaking changes introduced by v4.1. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v4.1
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v4.1.
-
Multiple .Take() calls on a query in Linq will no longer result in
'last Take wins' but will use the lowest number of the Take calls.
Example:
Original behavior (v2.6-4.0): would result in 20 rows. New behavior (v4.1+): results in 10 rows, as taking 20 rows from a set of at most 10 rows should never result in 20 rows. If your code relies on the original behavior, set LLBLGenProProviderBase.AlwaysUseLastSpecifiedTake to true (default is false).metaData.Customer.Take(10).Take(20);
- OData Support Classes are now build against WCF Data Services 5.6.0.
Migrating generated code from v3.5 to v4.0
To make migration as smooth as possible, perform the following steps:
- Load a copy of your LLBLGen Pro project file into the LLBLGen Pro designer
- Right-click the project node in Project Explorer, select 'Project Settings'. Navigate to 'Code Generation -> General' Make sure 'clean up vs.net projects' is checked. This setting makes sure the table valued functions factory TvfCallFactory.cs/vb (in the Factories folder) is added automatically to the generated code.
- Generate code on top of a copy of your v3.5 code base.
- Load your project's VS.NET solution into VS.NET
- Change the references to the v4.0 runtime libraries. You can also do this in notepad by editing the cs/vbproj file's XML.
- Remove references to LinqSupportClasses dll and QuerySpec dll as they're no longer needed.
- Selfservicing specific: If your project isn't set to cleanup the VS.NET project automatically during code generation, you have to manually remove the file 'TransactionComPlus.cs/vb' from the generated code project, if that class is still present.
Breaking changes v4.0
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v4.0. They are a result of refactoring a lot of code of the entity classes and related classes of both Adapter and SelfServicing for faster fetch operations. In general these breaking changes aren't affecting most users, only the people who have extended some classes or overriden the methods affected. Correcting these changes is easy and straight forward.
General breaking changes
- Entity.Validate() has been made protected. It's now a mandatory deprecated method (causes a compilation error) since v2.6 and starting with v4 the method is no longer available. EntityCore. AddInternalsToContext() now has a parameter, resetWhenNull.
- UnitOfWork(2).Commit doesn't throw ORMConcurrencyExceptions anymore if a delete of an entity doesn't succeed because the entity was already deleted and no restriction was specified. The exception is still thrown if a restriction has been specified and an entity delete results in 0 rows affected.
- Excluded fields are now enlisted in the resultset as: NULL as fieldname. This means the resultset layout is always the same, excluded fields or not. In general this isn't a breaking change, but if you rely on the resultset not having NULL values for excluded fields, your code needs adjustment. The change was made to make the resultset always be the same, to make code consuming the resultset easier and faster.
- DbSpecificCreatorBase.CreateValidAlias(string, bool) has been removed (also from the interface IDbSpecificCreator), instead simply use CreateValidAlias(string) and in your override of that method always check for quotes. As all DQEs now check for quotes in the alias method, if you created your own DQE and used the override with the boolean parameter, use the CreateValidAlias(string) instead.
- Several virtual methods have had their signature changed due to the introduction of QueryParameters. Normally you won't notice this, unless you've overriden methods which now receive a QueryParameters object instead of a list of parameters. To fix this,refactor your override to accept the QueryParameters object, which contains all the parameter objects which were previously passed into the method.
- DynamicQueryEngineBase.CreateInsertDQ/CreateUpdateDQ always created a BatchActionQuery, even if there was just 1 target. We refactored it to let it create only a BatchActionQuery if there are multiple targets, as the code was intended to do when it was first written back in 2005. In general you won't run into this change, unless your code relies on the fact the query created is always a BatchActionQuery. Instead, use the interface IActionQuery to work with the object returned. EntityCollection<T> / entityNameCollection.AddRange(IEnumerable) now doesn't raise a ListChanged.ItemAdded event after each item added to the collection, but one ListChanged.Reset event after all items have been added. This makes sure a bound EventView(2) won't update itself after each addition but just once.
- The default compatibility level for the Firebird DQE is now Firebird2x (was Firebird15). If you're using Firebird 1.5, set the compatibility at the start of your program on the Firebird DQE's DynamicQueryEngine directly, by setting the static/shared property DynamicQueryEngine.CompatibilityLevel to FirebirdCompatibilityLevel.Firebird15. You can also do this through your application's config file. See Application configuration through the config file for details.
- Linq related: the test for correlation predicates in nested queries is now more strict: it now also tests the operator of the predicate to be 'Equal', previously it didn't do that, it accepted any Field op Field predicate, which could lead to queries being accepted but with potentially wrong query results.
Breaking changes related to refactor EntityFields for faster fetches
- EntityFields(2).Contract() and .Compact() methods are no longer supported on EntityFields(2) objects which are part of an entity object. Expand() is still supported in that situation. In practice this has no high impact on existing code as entity classes which use fields objects with extra fields added to them in code don't contract/compact.
- EntityFields(2)[index] setter won't place the specified field object on the index specified, if the fields object is part of an entity, it will copy the value instead.
- EntityFields(2).IsDirty and .State are only vaild when the fields object is part of an entity. This is logical, as they make no sense when the fields object is used to build a query.
- IEntityFieldCore no longer has the methods AcceptChange and RejectChange. The pattern in which these methods are used never really worked properly anyway, and it's highly unlikely these methods are used in user code. If you use these methods, use SaveFields/RollbackFields instead.
- EntityCore. PreProcessValueToSet and EntityCore.PostProcessValueToGet no longer accept a field instance, but instead accept the IFieldInfo object of the field. This fieldinfo object, which contains the field index, can then be used to obtain the values and field info from the Fields object. This is done to avoid unnecessary field access internally, as fields are no longer created by default inside an entity. Use the field index to obtain values from the entity.Fields object through its IEntityFieldsCore interface.
- EntityCore.OnFieldValueChanged no longer accepts a field, but instead accepts the IFieldInfo of the field which value was set.
- The virtual method ReadRowIntoFields in DataAccessAdapterBase/DaoBase been removed. The method was only called when single entities were fetched, the multi-entity fetch pipeline skipped it altogether.
How to work with the EntityFields(2) objects without using entity fields in an entity
If your code accesses the entity field objects in e.g. validators or auditors, instead of reading field properties, you can now access the values you need directly from the entity.Fields object through its IEntityFieldsCore interface, instead of obtaining the EntityField(2) object and access its properties. The reason you should use IEntityFieldsCore's methods instead of obtaining a field object from the Fields object is that entity objects no longer create entity field objects by default. They use a new internal object which is more efficient and allows faster entity materialization after a fetch. When you use entity.Fields[index] the Fields object will create a new field object for you on the fly, through which you can access the information you needed. However creating this field object is unnecessary.
In general this means you should use methods like entity.Fields.GetCurrentValue(index) instead of entity.Fields[index].CurrentValue. The latter still works, but creates an EntityField(2) object, the former doesn't. Please see for details about the IEntityFieldsCore interface, the LLBLGen Pro Runtime Framework Reference Manual (LLBLGenPro.RTL.ReferenceManual.chm).
LinqSupportClasses and QuerySpec assemblies are now merged into ORMSupportClasses assembly
Starting with v4, the SD.LLBLGen.Pro.LinqSupportClasses assembly and the SD.LLBLGen.Pro.QuerySpec assembly are now merged into the SD.LLBLGen.Pro.ORMSupportClasses assembly. This makes things easier when referencing assemblies. If you migrate an existing v2.6 or v3.x code base to v4, you have make sure the references to the LinqSupportClasses and QuerySpec assemblies are removed as they're no longer needed.
.NET 3.5 or higher is now required; no more support for .NET 2.0 or .NET 3.0.
Starting with v4, the LLBLGen Pro runtime framework is compiled against .NET 3.5, and your software therefore requires .NET 3.5 as well. If you're migrating an existing code base to v4, you have to adjust the target framework in Visual Studio to at least .NET 3.5
SD.LLBLGen.Pro.ORMSupportClasses and DQE assemblies no longer have .NETxy suffix in file/assembly name
Starting with v4, the ORMSupportClasses and DQE assemblies no longer have a .NETxy suffix in the assembly and file name. If you specify the assembly names for references in webforms, you have to adjust them so they don't contain '.NET20' anymore.
SD.LLBLGen.Pro.ODataSupportClasses is now compiled against v5.3 of the WCF Data Services Server assembly
Starting with v4, the ODataSupportClasses have been compiled against v5.3 of the WCF Data Services Server assembly available from nuget, instead of the .NET 4 version of the same assembly. Your application will therefore need to reference this same assembly (or newer) to use ODataSupportClasses. The advantage is that you get OData v3 support out of the box, while still are able to use OData v1 and v2.
TDL Interpreter / parser code freeze
Starting with v4, no new functionality, except some small changes, has been added to the TDL interpreter / TDL parser. All new functionality will be written in .lpt templates. If you use the TDL interpreter in your templates, be aware that if you want to utilize new features like Table valued functions in your TDL templates you have to rewrite them in .lpt templates instead. It's possible to use an .lpt include template inside a TDL template.
Migrating generated code from v3.1 to v3.5
The following changes are breaking changes introduced by v3.5. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v3.5
The following breaking changes have been introduced in LLBLGen Pro Runtime Framework v3.5. They are a result of refactoring a lot of code of the entity classes and related classes of both Adapter and SelfServicing into a base class which is inherited by EntityBase and EntityBase2 so more code is re-used. In general these breaking changes aren't affecting most users, only the people who have extended some classes or overriden the methods affected. Correcting these changes is easy and straight forward.
Changed method signatures
- EntityBase.OnFieldValueChanged and EntityBase2.OnFieldValueChanged. The new method uses IEntityFieldCore instead of IEntityField/IEntityField2.
- EntityBase.PreProcessValueToSet and EntityBase2. PreProcessValueToSet. The new method uses IEntityFieldCore instead of IEntityField/IEntityField2.
- EntityBase.PostProcessValueToGet and EntityBase2. PostProcessValueToGet. The new method uses IEntityFieldCore instead of IEntityField/IEntityField2.
- EntityBase. SetRelatedEntityProperty and EntityBase. SetRelatedEntityProperty. The new methods use IEntityCore instead of IEntity or IEntity2.
- EntityBase WriteXml(XmlWriter writer, XmlFormatAspect aspects, string rootNodeName, Dictionary<Guid, IEntity> processedObjectIDs) and EntityBase WriteXml(XmlWriter writer, XmlFormatAspect aspects, string rootNodeName, Dictionary<Guid, IEntity2> processedObjectIDs). The new methods use IEntityCore instead of IEntity or IEntity2.
- AuditorBase.WriteXml. The new method now uses IEntityCore instead of IEntity2.
- EntityBase.PostReadXmlFixups. The method is now called PerformPostReadXmlFixups.
- EntityBase/EntityBase2.OnRelatedEntitySet/OnRelatedEntityUnset. The methods now have as entity type IEntityCore instead of IEntity or IEntity2.
- EntityBase/EntityBase2.SetRelatedEntity/UnsetRelatedEntity. The methods now have as entity type IEntityCore instead of IEntity or IEntity2.
- EntityBase/EntityBase2.OnSetRelatedEntityProperty. The method now has as entity type IEntityCore instead of IEntity / IEntity2.
-
ObjectGraphUtils methods. The methods in ObjectGraphUtils are
now mostly generic methods returning generic objects. In general
this doesn't have to be a problem, as the class is not often used
outside the runtime. If you get compilation issues, specify the
generic type explicitly, e.g.:
Dictionary<Type, IEntityCollection2> entitiesPerType = graphUtils.ProduceCollectionsPerTypeFromGraph<IEntityCollection2>(this);
No more COM+ support
All COM+ oriented code has been deprecated and is no longer included. This means that projects migrated to v3.5 and which are re-generated have to get rid of the COM+ based classes (automatic in Adapter, in SelfServicing, remove the TransactionComPlus helper class). COM+ using code should use System.Transactions instead.
ORMSupportClasses assembly is now split in two assemblies
To make the ORMSupportClasses and the generated code projects usable in .NET 4 client profile projects, we split up the ORMSupportClasses assembly into two assemblies:
- SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll The normal dll which contains all the base classes for using the generated code
- SD.LLBLGen.Pro.ORMSupportClasses.Web.dll The assembly which now contains the DataSource classes for Web usage and accompanying designers.
The net effect is that for web projects migrated to v3.5 which use the datasource controls, the assembly name of the datasource declaration has to change from SD.LLBLGen.Pro.ORMSupportClasses.NET20 to SD.LLBLGen.Pro.ORMSupportClasses.Web. Additionally, the version has to be adjusted to v3.5.0.0.
In general this change has to be made in the web.config file of the website. It's recommended to register the tag prefix 'llblgenpro' in the web.config file so you'll have the reference to the assembly in just 1 location, instead of on every page where a datasource control is used. In the case where the tag is registered on every page, the assembly name has to be changed in every <Register> element as described above.
To perform design-time actions, the datasource controls located in SD.LLBLGen.Pro.ORMSupportClasses.Web.dll have to be added to the toolbox, which makes them available when a webform is opened in VS.NET.
No more design time support for Entity Collection classes.
The Entity Collection classes no longer support design-time usage through a designer in VS.NET. In general it's not a good idea to drag an entity collection onto a Windows Form anyway, but in the past you could do so and, in adapter's case, get a designer which allowed you to pick the factory.
In v3.5 there's no longer design-time support for collections. In general this shouldn't be a big problem, as best practices say you should use the Data sources feature in VS.NET for this anyway: Instead of dragging/dropping an entity collection, configuring it at design time and at runtime filling it with data, do the following:
- Create a data source in the VS.NET project using the Data menu
- Select the entity type you want to bind through the data source
- Add a BindingSource to the form you want to bind entity data.
- Select the created data source as the DataSource of the binding source.
- Set the BindingSource as the DataSource of the control you want to bind to.
-
At runtime, bind a new entity collection to the BindingSource
instance by setting the DataSource property of the BindingSource to
the entity collection instance:
var toBind = new EntityCollection<CustomerEntity>(); // fetch it ... // bind it to the bindingsource myBindingSource.DataSource = toBind;
Projects migrated to v3.5 continue to work, but altering the design-time designed collections won't work as there aren't any designers anymore.
Obsolete methods
- The method entity.TestCurrentFieldValueForNull has been marked Obsolete, as the method is unnecessary. It will give a warning if you call this method in your code. Instead of calling this method, please use entity.Field==null.
- The method entity.CheckIfCurrentFieldValueIsNull has been marked Obsolete, as the method is unnecessary. It will give a warning if you call this method in your code. Instead of calling this method, please use entity.Field==null.
Migrating generated code from v3.0 to v3.1
The following changes are breaking changes introduced by v3.1. Please check them with your own project to make the transition as smoothly as possible.
Breaking changes v3.1
Templates
- In v3.0, when using multiple RDBMS types in a project (e.g. SqlServer and Oracle), generating code would result in database specific vs.net projects which have the database type name (e.g. SqlServer) twice e.g. MyRootNamespace.SqlServerSqlServer.Persistence.csproj). This has now been corrected. If you use multiple RDBMS types in your project and one of these target frameworks (Linq to Sql, Entity Framework or LLBLGen Pro runtime framework), generating code with v3.1 will result in a database specific project name with the database type name just once (so MyRootNamespace.SqlServer.Persistence.csproj for example). Existing solutions will refer to the old vs.net project file, so you manually have to correct the solution. To make it easy: before generating code with v3.1, rename your persistence projects so that the RDBMS type name is specified just once. Do this in vs.net, so the .sln file is updated as well. After that, regenerate code with v3.1, so the code generator will update your existing vs.net projects. If you dont want this: in the preset you use, specify [databaseShortName] in the filename parameter for the vs.net project task in the preset at the spot after [projectName] or where the redundant name was specified. Then save the preset as a custom preset and use this preset from now on.
Runtime libraries
- If you use type converters, make sure that they can handle null-values: type converters now get passed in null (Nothing in VB.NET) instead of DBNull.Value. This was actually already a breaking change in v3.0.
- SQL Server DQE specific: The static property DynamicQueryEngine.CompatibilityLevel has been renamed to DynamicQueryEngine.DefaultCompatibilityLevel. A new, instance property has been added, CompatibilityLevel which sets the compatibility level per instance. Its not likely you run into this, as its recommended to set the compatibility level in the config file or once through the DataAccessAdapter class or CommonDaoBase class.
Migrating generated code from v2.6 to v3.0
The following changes are breaking changes introduced by v3.0. Please check them with your own project to make the transition as smoothly as possible.
Features no longer supported in 3.0
The following features are no longer supported:
- Compact Framework. Starting with v3.0, we only support full versions of the .NET framework
- .NET 1.0 and .NET 1.1. The LLBLGen Pro Runtime Framework v3.0 supports .NET 2.0 and higher, and no longer .NET 1.0 or .NET 1.1. This also means there's no support for VS.NET 2002 and VS.NET 2003 anymore
- Oracle 8i. Oracle has dropped support (publically) for Oracle 8i years ago, and LLBLGen Pro v3.0 also doesn't support Oracle 8i anymore.
Breaking changes v3.0
Templates
- .NET 1.x / VS.NET 2002/2003 are no longer supported.
- Compact Framework is no longer supported.
- Sub-types now always inherit their PK fields from their super-type, their own PK fields always have the same names.
- Fields have no index anymore. This leads to a problem in which order PK fields and UC fields are emitted into the method signatures. The fields are ordered by their name, ascending. This could lead to a breaking change when migrating v2.x code to v3.x when a compound PK or UC with two or more fields with the same type are used. You have to examine calls to the fetch methods using PK and UC directives as well as CTor calls to entities with a PK of 2 or more fields.
- Oracle, ODP.NET: Calling a retrieval stored procedure with one or more cursors will give default datatable names, instead of the names of the cursor parameters. This is necessary because there's no notion of what an OracleCursor object is as there's no reference to ODP.NET
- Stored procedure call code no longer has overloads which accept/return ReturnValue values.
- If an output parameter of a stored procedure is NULL, in previous versions the method member was left untouched. In v3, the member is set to null if the member is of type Nullable<T> and the default value for the type if the member is of another type. Default value is calculated with the FieldUtilities class: string has as default value string.Empty, guid: empty guid and byte[]: empty array.
- VB.NET, 2010 specific: Starting with VS.NET 2010, the build output folders are bindebug and binrelease, instead of just bin, which is equal to the pattern VS.NET uses.
- SelfServicing: DbUtils has been removed. The static settings and methods are moved to the DaoBase class. The Db specific methods for sqlserver, like SetArithAbortFlag and SetSqlserverCompatibilityLevel are moved to the new class CommonDaoBase, which is located in the DaoClasses namespace. As DbUtils' public properties are not used frequently in an application, breaking code is minimal: rename the call / reference to the DbUtils member to a call to the CommonDaoBase class method / property instead. The DbUtils.CreateTransaction(3) method has been removed (there's no replacement in CommonDaoBase). The reason is that 'name' is no longer used. Use the overload which don't accept a name. This method also has been moved to DaoBase / IDao and is now no longer static. It's not likely you use this method in practice.
- Adapter: DataAccessAdapter is now generated using a shared template. This means that a lot of code has been moved to the base class.One of the methods which is moved is the InsertPersistenceLogic for predicates. This method contained a user code region in the default (case else) clause. If you had code added to that region, please override OnInsertPersistenceObjects() in a partial class of DataAccessAdapter and add your code to that method instead.
- The connection string key name has changed. Please check the generated app.config file in the DbSpecific project (adapter) or the generated code project (selfservicing) for details on the connection string key name and copy it over to your application's app/web.config file.
Runtime Libraries
- Oracle ODP.NET: There's now just 1 DQE for ODP.NET, instead of 1. If using Oracle 8i, you have to switch off Ansi Joins using the Application Configuration file settings as Ansi joins are now enabled by default.
- SQL Server: The default compatibility level is now set to SQL Server 2005. If you're using SQL Server 2000, you have to set the compatibility level to 1 through the Application Configuration file settings. Code targeting SQL Server 2000 which is generated using the default compatibility level will likely crash due to exceptions as the SQL can be incompatible (TOP clauses using parameters, CTE based paging etc.)
- Firebird. The FirebirdCompatibilityLevel enum is now located in the ORMSupportClasses assembly.
- Some methods have been removed or made private. In general this shouldn't be a problem as they weren't meant for usage outside the framework itself. If you use a method like GetFieldByName, use the string indexer on the Fields object in the entity instead.
Migrating generated code from v2.5 to v2.6
A lot of the breaking changes are made on the .NET 2.0+ code only. This is due to the fact that the .NET 1.x codebase has reached its end of life (as well as the CF.NET 1.x code). LLBLGen Pro v2.6 does ship with .NET 1.x code support, but not a lot of the changes in v2.6 are made to that codebase as well. You're encouraged to upgrade to at least .NET 2.0.
Breaking changes v2.6
Runtime libraries
- Due to heavy refactoring, some of the protected methods of DaoBase and DataAccessAdapter which were used internally for for example prefetch path execution have been moved to another class, PersistenceCore and made internal static. If your code relies on these methods, please rewrite your code so they don't rely on these methods anymore. This and other refactorings were performed to remove clones inside the codebase and to make the code more maintainable.
- RelationCollection and IRelationCollection’s indexer now returns an IRelation instead of IEntityRelation. This indexer (Item in VB.NET) returns either an IEntityRelation or an IDynamicRelation object, which derive from IRelation
- SelfServicing: in prefetch paths, the intermediate entity in m:n relations is now aliased with the same pattern as the GetMultiManyToManyField method uses: Entityname. Example: "Order". Previously this was an empty string. Adapter already uses this pattern.
- .NET 2.0+: IEntityFactory(2).CreateHierarchyRelations() isn't virtual anymore. Instead, override the new IEntityFactory(2).CreateHierarchyRelations(string) method.
- .NET 2.0+: IEntityFactory2.GetEntityTypeFilter(bool) isn't virtual anymore. Instead, override the new IEntityFactory2.GetEntityTypeFilter(bool, string).
- DbFunctionCall now doesn't ignore schema or catalog names specified anymore when the function name is a pre-formatted string. This doesn't normally lead to breaking code as the names were ignored previously, but just in case you passed the names, they're now having effect.
- IProjection has new members, which you have to implement in your code if you implemented IProjection previously.
- IPredicate now has 2 new interface members: GetFrameworkElementsInPredicate() (method) and ObjectAlias (property). Custom predicate implementation have to make sure these members return the correct values with respect to the custom predicate. ObjectAlias is now implemented on Predicate, the abstract base class of all predicates. If your custom predicate inherits from this class, you can remove the ObjectAlias property from your predicate. GetFrameworkElementsInPredicate returns a list of objects, which are all LLBLGen Pro framework elements, so entity fields, expression objects and the like, contained inside the predicate.
- .NET 2.0+: IEntityField.ToXml has been removed.
- .NET 2.0+: EntityField and EntityField2 have been refactored to use a shared base class, EntityFieldCore. This could lead to deserialization problems if you deserialize binary serialized predicates back which are serialized using older runtime versions
- .NET 2.0+: EntityField/EntityField2 now consume less memory (-20%) as elements which aren’t used with entities are factored into separate classes/objects. This brings down memory consumption in fields, though could lead to errors during deserialization if you deserialize binary serialized predicates back which are serialized using older runtime versions
- .NET 2.0+, SqlServer, CE: On .NET 2.0+, SqlServer CE 3.0 or higher is supported, as the DQE uses named parameters in the queries. If you're using an older version of SqlServer CE, you've to upgrade to that newer version, recommended is v3.5 or higher.
- .NET 2.0+, SqlServer, CE Desktop: LLBLGen Pro now uses the normal SqlServer DQE for generating queries for SqlServer CE Desktop, so migrating an existing CE Desktop targeting VS.NET project to v2.6 requires that you change the references to the SqlServer DQE. You also have to set the SqlServerCompatibilityLevel in your application's .config file to 3 for SqlServerCE 3.x and 4 for SqlServerCE 3.5
- If you’re using your own VS.NET templates, the <[RuntimeLibraryHintPath]> token is no longer used. You’ve to append the .NET version number, e.g.: <[RuntimeLibraryHintPath20]> for .NET 2.0 runtime libraries.
- If you add the same entity object twice to a collection, which is contained inside an entity, e.g. you add myOrder twice to myCustomer.Orders, it is now added twice and not as before, added once. If you set the property DoNotPerformAddIfPresent to true on the collection, the entity is added once. DoNotPerformAddIfPresent is false by default. This change is caused by the fact that if you set a property mapped onto a relation to the same object (e.g. myOrder.Customer = myCustomer; where myOrder.Customer was already set to myCustomer), it’s no longer desynced and re-synced, the set is a simple no-op, as nothing has to be done. This means that if you add myOrder twice to myCustomer.Orders, it’s no longer first desynced from myCustomer, and therefore it’s not removed from the collection before it’s added. Normally this isn’t a problem, only when you tend to add entities multiple times to a collection, have DoNotPerformAddIfPresent set to false and rely on the # of entities in the collection. To work around this: either set the flag DoNotPerformAddIfPresent to true or prevent adding the same entity twice, if you really have to rely on the # of unique entities in a collection.
- .NET 2.0+: When CancelEdit() is called (either by manual code or by a bound control) on an entity, for every field which was changed during the edit cycle, PropertyChanged is now raised. This makes bound controls reflect the reset values for the fields changed, as the fields were reset to their values prior the edit cycle was started.
- IViewProjectionData doesn’t have a method CreateDataRelations anymore. This method has been moved to the new GeneralUtils class as a static method.
- Hierarchical projections from entity collections to DataSet don’t clear the DataSet’s Tables collection anymore, so if you pass a DataSet with tables, they won’t be removed.
- .NET 2.0+: TypedListBase, TypedListBase2 and TypedViewBase are now generic classes.
- When a project is re-generated into an existing directory in which the code of a previous generation cycle is located, the cs/vbproj file(s) won’t get their rootnamespace set again. Initially when a cs/vbproj file is generated, the rootnamespace is set, and in previous versions of LLBLGen Pro, the rootnamespace name was overwritten also if the cs/vbproj file was altered in subsequential code geneneration cycles. This overwriting has been removed: if you alter the namespace after the first code generation cycle, it won’t be reset. Normally you won’t notice this unless you add classes to the generated code yourself.
- The default culture used for XML serialization is now set to the invariant culture. This culture is controlled by the XmlHelper.CultureNameForXmlValueConversion property or the .config file setting cultureNameForXmlValueConversion. Previously it was set to the current culture of the executing thread. If you want to use a different culture you’ve to set the property or the config setting.
- The TDL statements <[IsForeignKey]> and <[If IsForeignKey]> now result in true if the relation is still visible but the field mapped onto the relation is hidden. This was previously not the case: if the field mapped onto the relation was hidden but the relation was still there, these statements would result in false.
- Oracle drivers targeting ODP.NET will now throw out stored procedures with parameters or a returnvalue of type BOOLEAN. This is because ODP.NET can't deal with BOOLEAN typed parameters on procs, so allowing them will result in runtime exceptions.
- .NET 2.0+: EntityBase/EntityBase2 no longer use the method called FlagAllFieldsAsChanged. This method was used by RollbackFields to simply raise changed events for all fields in the entity. However this is inefficient if a low number of none fields were actually changed. This has been fixed internally. So relying on the call to FlagAllFieldsAsChanged from RollbackFields is no longer going to work: the method is no longer called. The method is still there if you want to use it to flag all fields as changed.
- .NET 2.0+: EntityBase/EntityBase2 no longer raise for all fields in an entity a changed event if RollbackFields is called: they now only raise a changed event for fields which were changed due to the rollback.
Templates, generated code.
- .NET 2.0+, SqlServer: The SqlServer templates and DQE now use the DbProviderFactories class to produce connections, commands and the like based on the compatibility setting inside the DQE. This has the advantage that you can switch between SqlServer server and SqlServer CE Desktop without regenerating/recompiling any code: just change a config setting in the .config file of your application and by changing the connection string. It is however a breaking change because the CE Desktop-using developers have to use different templates: the SqlServer CE templates aren't available anymore on the .NET 2.0/3.x+ platforms. Furthermore, referencing SqlServerCe dll isn't required anymore, as long as the provider is registered in the .config file of the application or in the machine.config file of the .NET 2.0 framework. See the SqlServer CE documentation and the MSDN documentation for details about DbProviderFactories. NOTE: if you use views, stored procedures and/or types in your sqlserver database which aren't supported in the SqlServer CE Desktop version you're using, you'll get errors at runtime. Please check this up front.