What's new/changed in LLBLGen Pro Runtime Framework v5.4?
Below you'll find a list of changes, additions and important fixes in the 5.4 release of the LLBLGen Pro Runtime Framework. It's recommended you also browse the Migrating your code section for breaking changes and how to migrate your current project with generated code to v5.4.
What's new in LLBLGen Pro v5.4
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v5.4
New functionality / changes
- Generated code is now much smaller, especially for Adapter. This leads to faster compilation times and faster code generation times (on top of the faster
code generator in v5.4). A lot of code has been moved to the base classes
EntityBase
andEntityBase2
. These changes have no negative memory impact nor performance impact, in fact memory consumption in prefetch paths is slightly better now. - The PlainSQL API now has a feature to perform implicit conversions of types, meaning a value of type T1 in the resultset can be implicitly converted to type T2 in the projection class, if an implicit conversion is defined for T1 and T2 (e.g. short to int)
- Poco Typed List fetch methods in Linq and QuerySpec now have an optional query argument to be used as the root query, allowing you to specify a richer query than the generated query for the typed list.
- PostgreSQL 10.x is now a supported database, which includes support for the new Identity fields in PostgreSQL 10.x
- Empty methods for Field-mapped-onto-related-field event handlers are now avoided and code is less verbose
- UnitOfWork and UnitOfWork2 now have a property
IsEmpty
which returns true if no work is scheduled in the unit of work instance. This property is also implemented in the interfaceIUnitOfWorkCore
. - PostgreSql: the query generated for directly deleting entities using a join with another table now no longer uses non-ansi joins but uses a proper ansi-join using correlated subquery.
- When fetching prefetch paths with a paging query, the runtime now automatically switches over to parametrized IN clauses for the prefetch path sub paths, no matter the value for the
ParameterizedPrefetchPathThreshold
. This avoids that all rows in the target of a sub path node are fetched and filtered on the client. This is now also done if a limit is specified for the root node and no paging is performed, the runtime in that situation now also picks the parameterized route.
It can lead to a crash if the page is too large, and too much parameters are issued for the sub path query. This is equal to the user setting the ParameterizedPrefetchPathThreshold
to a value higher than the maximum amount of parameters allowed by the database. The solution to this is to use a smaller page size so the # of elements in a page is smaller than the max number of parameters for a database.
- The PostgreSQL DQE now uses the
RETURNING
clause to return sequenced fields in an insert query instead of a separate scalar query which used a separate roundtrip; each insert query is always one roundtrip, even if there are sequenced fields involved. - SelfServicing:
DeleteMulti
/UpdateMulti
and async variants are now virtual. - Using
FetchProjection<T>(retrievalQuery)
orFetchQuery<T>(plainSqlString)
where T is a valuetype likeInt32
or a system type likestring
, the query would fail in previous versions but will now succeed with returning a list of values (the values of the first column in the resultset), all typed T.
What's new in LLBLGen Pro v5.3
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v5.3
New functionality / changes
- .NET Standard 2.0 support. The LLBLGen Pro Runtime Framework can now be used on .NET Standard 2.0 supporting platforms like .NET Core 2.0 and Xamarin. Please see the .NET Standard support page for details regarding the small amount of limitations you might run into.
- New RuntimeConfiguration system to configure LLBLGen Pro Runtime Framework specific behavior and settings in code instead of in .config files. Mainly meant for .NET Standard 2.0 using applications but it's also available for .NET Full.
- The Plain SQL API now has a
FetchScalarQuery<T>
method to retrieve a scalar value from the DB using a plain SQL query. More information. - Query tagging. Linq and QuerySpec have the ability now to let you mark (tag) the SQL query or queries generated by the runtime with a tag. This tag is a string which is added as a comment before the actual query string. This way you can easily track back the SQL query on a database server with the actual calling code without a profiler / stacktrace. It's a low-impact way to make sure you can track down information at runtime in the future. More information: Linq, QuerySpec.
Small changes
- The Runtime Framework is now compiled against .NET 4.5.2
- QuerySpec: When a scalar query is executed using
FetchScalar<T>
and T isn't a nullable type and the query returns a NULL value, the cast to T would result in a Null reference exception. We now added a check first which will throw an InvalidOperationException if a null value was returned and the type specified isn't a nullable type. - Lambda caches and factory caches are now using a ConcurrentDictionary instead of a Dictionary per thread, which should save some memory in large applications.
- QuerySpec: an extension method has been added for ISortClause,
DontEmitAliasForExpressionAggregateField
, so the EmitAliasForExpressionAggregateField flag can be set using the fluent interface. See the LLBLGen Pro Runtime Framework Reference Manual for details. - A new exception class has been added:
ORMConfigurationException
. This exception is thrown when an error is detected in the RuntimeConfiguration usage. - Prefetch path fetches with a context are now using faster merges as the linear searches caused by the context usage in collections during merges are now no longer happening. This is done when the fetch is into a new graph. An existing graph will do the linear searches during merge as before.
- Nuget: the packages for DQEs now reference a specific ORMSupportClasses version, which means you always have to update both when referencing a specific DQE package version. Previously we defined a range of
[currentversion-nextmajorversion)
but that is too large and causes 'downgrades' for .NET Core due to a change in the way downgrade warnings are handled by the .NET Core tooling. - Field compare value predicate now detects value truncation for variable string typed parameters. If it detects truncation, it will emit "1=0" instead of the actual predicate, followed by a comment to make the predicate result in 0 rows. Value truncation occurs if the DbParameter's Value property is set to a value which has a length longer than the 'size' property. The size property of the parameter is set to the length of the field compared against. So if you compare a varchar(20) typed field F to a string with length 25, you'll get 1=0 instead of the comparison of the first 20 chars of the string with the field, which could lead to matches which are unintentional.
- Field value equality comparisons of byte array values are now more optimal.
- Firebird 3.0 support. LLBLGen Pro Runtime Framework now supports Firebird 3.0. This effectively means that the new Boolean type is now fully recognized. The identity field support of Firebird 3.0 will be added as soon as the Firebird Client supports this.
What's new in LLBLGen Pro v5.2
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v5.2
New functionality / changes
- Data Scope now has Async / Await variants of its methods so it can be used fully asynchronously.
- A global flag has been added for SelfServicing to disable lazy loading with one setting:
EntityBase.EnableLazyLoading
. The flag is enabled by default (so lazy loading is enabled by default) for backwards compatibility. - Lots of string interpolation has been refactored to more efficient string usage, resulting in faster performance overall and even lower memory footprint/object pressure. LLBLGen Pro is now the fastest ORM, beating all microORMs too (using the plain sql API).
- Size specification on
Init()
methods in the generatedFieldInfoProvider
andPersistenceInfoProvider
classes have been removed, so merge conflicts will no longer occur when merging different code bases of generated code. - For new projects and projects which change the target framework to the LLBLGen Pro Runtime Framework, the default output type for TypedLists and TypedViews has been changed to PocoWithQuerySpecQuery. This was TypedDataTable. If you still want to use TypedDataTable as the outputtype for TypedLists and TypedViews, you can change the default in the LLBLGen Pro Runtime Framework settings in the Project Settings. The default choice is for QuerySpec and not Linq because typed views mapped onto stored procedure resultsets aren't supported in Linq but are supported with QuerySpec. For existing projects the old default is kept.
- Linq/QuerySpec: Using 'Distinct' on a subquery which is used inside an 'IN()' clause is now used inside the subquery. This is due to an addition in the FieldCompareSetPredicate which now allows 'Distinct' in the subquery. For most databases the 'Distinct' in the subquery has no effect, but on e.g. Oracle it can help the optimizer to pick an index instead of doing a table scan.
AddCollectionForSave
andAddCollectionForDelete
are now part ofIUnitOfWorkCore
.DataAccessAdapter.SaveTransaction(name)
andTransaction.SaveTransaction(name)
no longer throw an exception whenname
was already used within the same transaction, as all supported databases which do support savepoints support multiple savepoints with the same name in a single transaction so the check / limitation is unnecessary.- Entity field validation now doesn't report a precision overflow for decimals/floats/doubles with precision equal to scale and a value between (-1.0, 1.0) excluded. Even though the precision of a value in that interval, e.g.
0.55
, is 3, the leading zero isn't taken into account by databases and therefore the runtime shouldn't either.
What's new in LLBLGen Pro v5.1
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v5.1
New functionality / changes
QuerySpec
- Easier projection definitions. It's now easier to define a projection to a POCO when you want to specify a set of fields in a Select. More information: Projections in QuerySpec
General
- Temporal (History) Table support:. For SQL Server 2016 and higher/ DB2, temporal tables are now supported through Linq / QuerySpec (Select / fetch queries only). Temporal tables are an easy, friction free way to store previous versions of modified / deleted rows in a table. The temporal table support in LLBLGen Pro allows you to include older versions of entities when querying. More information: Linq, QuerySpec
- Hints support. For SQL Server / MySQL, select target hints are now supported through Linq and QuerySpec. More information: Linq, QuerySpec
- Plain SQL API. You can now execute plain SQL statements using parameters directly onto the database, including fetching resultsets and projecting the resultsets to POCO classes. With this API you don't need a microORM on the side anymore for those situations where the runtime couldn't give you the right query. This API is also very fast: fetching a query through this API is faster than most microORMs. See: Results from 21 September 2016. These results were determined using RawDataAccessBencher. More information: Plain SQL API.
- Easier projections from stored procedures. It's now easier to create projections of stored procedure resultsets onto POCO classes, all it takes is specifying the target type. More information: Adapter, SelfServicing
What's new in LLBLGen Pro v5.0
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v5.0
New functionality / changes
- Linq: It's now possible to use
Union()
in the last projection in the query (the most outer projection). TheUnion()
call is not executed in the database but in the projection code itself. UsingUnion()
elsewhere in the query will still lead to an error asUnion()
isn't supported in LLBLGen Pro queries. IDataAccessAdapter.KeepTrackOfTransactionParticipants
has been added. The flag (default true) is used to signal the adapter that entities participating in a transaction controlled by this adapter are tracked during the transaction and which values are rolled back after a rollback of the transaction itself. Only set this flag to false if the entities participating in a transaction are not kept in memory during or after the transaction's life time.- Queries using projections in Linq or QuerySpec are now 30-40% faster than in v4.2 and are in general faster than a lot of the existing MicroORMs. See: https://github.com/FransBouma/RawDataAccessBencher, results from December 16th, 2015.
-
QuerySpec now defines a CaseInsensitive extension method for FieldCompareValuePredicate to set it into CaseInsensitive mode:
IPredicate p = CustomerFields.CompanyName.Equal("Foo Inc").CaseInsensitive();
-
QuerySpec now defines a CaseInsensitive extension method for
ISortClause
to set it into CaseInsensitive mode:ISortClause s = CustomerFields.CompanyName.Descending().CaseInsensitive();
- Various changes in the Linq provider to make it more robust.
- The static variable
EntityCore.MakeSettingNonNullableFieldsToNullFatal
has been added (default: false, for backwards compatibility), to make setting a non-nullable field to null throw anArgumentOutOfRangeException
. - SQL Server 2016 is now a supported database (through the SQL Server DQE/templates). Use 2012 compatibility to utilize the 2012 or higher features.
What's new in LLBLGen Pro v4.2
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v4.2
New functionality / changes
General
- Allowed Action Combinations: Specify which actions are allowed on an entity instance: Any combination of Create/Read/Update/Delete. Action Combinations make it easy to define e.g. entities which can only be created or read but never updated nor deleted. The action combinations are defined at the mapping level and checked inside the runtime and are additional to the authorization framework. More information...
- Expression support during Inserts It's now possible to define an expression on an entity field which is used during inserts. The expression defined is used to produce the field value. More information...
- Generate Typed Lists as POCO classes with a Linq or QuerySpec query. It's now possible to generate a typed list or all typed lists (controllable through settings) as a simple POCO class which holds the data of a row in the resultset and a Linq or QuerySpec query to execute the typed list. Adapter, SelfServicing
- Generate Typed Views as POCO classes and use them in Linq and QuerySpec. It's now possible to generate a typed view or all typed views (controllable through settings) as a simple POCO class and use it in Linq or QuerySpec queries. Adapter, SelfServicing
- Transparent Transient Error Recovery (adapter only). The transient error recovery system introduced in v4.1 has been upgraded so it can now be used transparently: define once and it is automatically used when executing a query. It's no longer necessary to explicitly execute a query through a recovery strategy. More information...
- Cached resultset tagging for easy cache purge/retrieval It's now possible to tag a query's resultset if that resultset is cached so the resultset can be retrieved from the cache using the tag and also it's now possible to purge the resultset(s) associated with the tag from the cache. More information...
- Exclude prefetch path nodes from resultset caching. It's now possible to exclude a prefetch path node from being cached if the root query has a resultset caching directive. More information...
Small changes / fixes
-
QuerySpec: Multiple calls to
query.From(operand)
are now appending the operand to the existing From clause if operand starts withQueryTarget
. If it doesn't start withQueryTarget
and there's an existingFrom
clause, it will overwrite the existingFrom
clause. -
OData: The OData Support Classes now support the
IgnorePropertiesAttribute
on entity classes. The names specified using the attribute have to be defined on the entity type the attribute is defined on, so inherited properties can't be filtered out using this attribute. - Low level api: Duplicate sort clauses are now filtered out so accidentally added duplicates through e.g. OData are no longer causing exceptions at runtime.
-
Dynamic Query Engines: when the source of a field isn't known, the
field creator functionality will no longer emit a dangling
.
but will simply only emit the field name/alias. This way constucts like.OrderBy("Name".Ascending())
will work, where the engine will emitORDER BY [Name] ASC
. Previously the above construct would result inORDER BY .[Name] ASC
which would fail. -
Query traces: The value of a parameter of type
DateTime
value in a query is now emited as a ISO 8601 / Roundtrip formatted string, which is more precise than the previousToString()
call on theDateTime
which didn't include fractions of a second. -
FunctionMappings added
(Linq/QuerySpec):
sbyte/byte/ushort/short/uint/int/ulong/long.ToString()
mappings have been added to all DQEs for all databases. -
EntityBase(2).AllowReadsFromDeletedEntities
allows code to read from an entity that has been marked as deleted. It's been set to 'false' as the default which will result in an exception if code reads from a deleted entity, like in previous versions. - SQL Server 2014 is now a supported database (through the SQL Server DQE/templates). Use 2012 compatibility to utilize the 2012 or higher features.
- Catalog name is now supported in sequence name, if applicable. In SQL Server, a catalog name can be present in the sequence name, and should be overwritten if required. In previous versions, the catalog name was ignored, only schema names were supported with a sequence name.
- FIX: QuerySpec: A projection lambda was created using a parameter which was created for every new query, which resulted in a new cache key for the lambda so the lambda was compiled every time instead of re-using a cached version. The lambda is now created using the same parameter as the original and the compiled version cached is re-used in subsequential executions of the same projection so query creation is a bit quicker.
-
FIX: QuerySpec: QuerySpec doesn't properly replace function mappings in derived tables. Queries like the following now work:
var qf = new QueryFactory(); var qs = qf.Create("S") .Select(DateTimeFunctions.Year(OrderFields.OrderDate).As("YearOrder")); var q = qf.Create() .Select(qf.Field("S", "YearOrder")) .From(qs);
-
QuerySpec: There's now a class available to create a projection
lambda quickly for
Select<T>()
calls, calledProjectionLambdaCreator
. This class has two overloads of itsCreate()
method which creates at runtime a projection lambda for T from either a specified fields set or a fields creation class (e.g.CustomerFields
). The overload which accepts the fields creation class caches the created lambda and is therefore much faster than a lambda created in code and compiled by the C# / VB.NET compiler which will create a newExpression<Func<T>>
at runtime each time it is run.
Usage:
Here, thevar qf = new QueryFactory(); var q = qf.Create() .Select(ProjectionLambdaCreator.Create<OrderPocoQsRow, OrderPocoQsFields>()) .Where(OrderPocoQsFields.CustomerId == "ALFKI");
ProjectionLambdaCreator
creates a lambda for theOrderPocoQsRow
, which is equal to the code below which was what you had to write in v4.1 and earlier:
The advantage is that the// equivalent code, prior v4.2 //... .Select(() => new NW26.Adapter.TypedViewClasses.OrderPocoQsRow() { CustomerId = OrderPocoQsFields.CustomerId.ToValue<System.String>(), EmployeeId = OrderPocoQsFields.EmployeeId.ToValue<Nullable<System.Int32>>(), Freight = OrderPocoQsFields.Freight.ToValue<Nullable<System.Decimal>>(), // etc. all fields specified. }) //..
ProjectionLambdaCreator
call caches its lambda under the two types specified while the written out lambda creation code will create a new one each time it is run. Running the code about 100,000 times takes 98ms for theProjectionLambdaCreator
and 19832ms for the written out code, so it does make a difference. -
QuerQuerySpec: There's now a special
Select
method available which produces its own lambda projector from two types given:
This method,var qf = new QueryFactory(); var q = qf.Create.Select<SomeDTO, SomeElementFields>();
dynamicQuery.Select<T, U>()
creates a projection and projector lambda fromT
andU
fordynamicQuery
and makes it aDynamicQuery<T>
. The typeT
is the type of a class which instances are returned by the createdDynamicQuery<T>
, and can be an entity type or DTO or e.g. generated typed view type. The typeU
is the type of the generated helper class which creates the fields forT
, e.g.CustomerFields
. -
QuerySpec: The usage of
QueryTarget
is now also supported inDynamicQuery / DynamicQuery<T>
instances, but only in appending join operands to an existing query:var q = qf.Create() .From(qf.Customer.InnerJoin(qf.Order) .On(CustomerFields.CustomerId.Equal(OrderFields.CustomerId))); //.... q.From(QueryTarget.InnerJoin(qf.OrderDetails) .On(OrderFields.OrderID.Equal(OrderDetailFields.OrderId)));
-
QuerySpec. you don't need to create a new field for each targeted
subquery field anymore, if you want to effectively clone the
projection of a subquery. It's now possible to clone a projection of
a derived table/aliased subquery in an outer query's
Select()
method. - It's now possible to generate case insensitive SQL for case sensitive databases using a setting.
What's new in LLBLGen Pro v4.1
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v4.1
New functionality / changes
General
- Full async API. The runtime framework now offers a full Async API, usable in Linq, QuerySpec and the Low-Level API for retrieval of data and object persistence. Usable in async/await code on .NET 4.5 and higher. More information...
- Transient Error Recovery The runtime framework now offers the ability to recover from transient errors occuring during database activity. More information...
-
Oracle 12c support The runtime now supports Oracle 12c:
Identity/default sequences are now supported on Oracle 12c as well
as the new paging keywords for
SELECT
on Oracle 12c. - Managed Oracle ODP.NET provider support The runtime now supports the managed ODP.NET provider for Oracle (v12+ of ODP.NET).
Changed
- The default for the designer setting TdlEmitTimeDateInOutputFiles has been changed to false.
-
LinqMetaData now has an overload of
GetQueryableForEntity
:GetQueryableForEntity<TEntity>()
, which accepts a generic type and returns aDataSource
(2) object for the given entity type. -
If a sequence retrieval query(fragment) returns null before/after an
insert, due to wrong sequence semantics or the field isn't marked as
identity in the database while the mapping code defines it as a
sequenced field, an exception of type
ORMBadSequenceException
is now thrown. The exception contains the query executed. -
CachingController
now has a static public field,CachingEnabled
(default true), which controls whether the caching controller caches resultsets (true, default), or silently doesn't cache any resultsets (false). Useful when debugging code which otherwise would cache the resultset. -
To QuerySpec the fluent extension method
IEntityRelation.SetCustomFilter
(..) (2 overloads) has been added to easily set a custom filter on a relation specified in a queryspec query. This extension method, as most QuerySpec extension methods, is also usable with the low-level API. -
Adapter now has a new method on entities:
DetachFromGraph
. This method will detach the entity it's called on from its referenced entities, including m:n relations. It will only dereference from the entities it knows of at runtime. -
BREAKING CHANGE:
Multiple
.Take()
calls on a query in Linq will no longer result in 'last Take wins' but will use the lowest number of theTake
calls. - BREAKING CHANGE:OData Support Classes are now build against WCF Data Services 5.6.0.
What's new in LLBLGen Pro v4.0
Below you'll find what's been introduced in LLBLGen Pro Runtime Framework v4.0
New functionality / changes
General
- 50% faster entity fetches. An extensive refactoring of the internal storage of values inside an entity instance resulted in up to 50% faster entity fetches. As entity instances don't have Entity Field instances to store their values anymore (though from the outside it will appear they will, so no code will break), memory footprints are smaller too. See http://pastebin.com/AdsKitr3 for a benchmark of how much faster the fetches are compared to v3.5 and other ORMs.
- Extensible Query Result Caching. It's now possible to specify (in Linq or QuerySpec, and with minor effort also with low-level API calls) a query result cache directive to tell the runtime to cache the results for that particular query for a given amount of time. The caching system is build around an easy interface, making it easy to extend it with own cache providers for cache systems like Redis. More information...
- Table Valued Function support. It's now possible, using Linq and QuerySpec, to fetch entities and typed views which are mapped onto a table valued function resultset. Linq, QuerySpec
- DataScopes. The runtime framework now offers DataScopes which greatly help managing data in memory in desktop applications. More information...
- Runtime Libraries are now compiled against .NET 3.5. The minimum .NET version supported by the runtime framework is now .NET 3.5.
- LinqSupportClasses and QuerySpec assemblies are now merged into ORMSupportClasses. The 3 assemblies are now merged into one, SD.LLBLGen.Pro.ORMSupportClasses.dll. This makes referencing assemblies simpler.
- Inlining of Value Type Definitions in the designer. It's now possible to in-line value type definitions in the designer, which makes modeling LLBLGen Pro projects simpler. More information...
- SQL Server 2012 sequences support The runtime framework now supports SQL Server 2012 sequences in insert queries.
- TypedLists can now be fetched using QuerySpec. Before, the low-level API had to be used to fetch typedlists. In v4.0 we made it possible to fetch TypedLists using the more powerful QuerySpec query API.
-
True skip/offset support. It's now possible to skip n rows in a
fetch without the requirement that the number of rows fetched is a
multiply of n. This is in line with how Skip works in Linq.
QuerySpec now has a new operator,
Offset(n)
which offers the same functionality. -
Char <-> String(1) built-in type converter. The runtime
framework now has a built-in type conversion for
char
<->string(1)
, to make it possible to have a DB field of typechar(1)
be used as a .NET char typed field. - Support for OData v3. The ODataSupportClasses now support OData v3 and are now compiled against WCF Data Services v5.3.
- QueryExecution Tracer. A new tracer has been added, to trace the actual query being executed. This information was already available through other tracers, but as these also emitted other information it could lead to a lot of data just to see which query was actually executed. This tracer solves that.
- All low-level query API elements, including UnitofWork2, are now XML Serializable. All low-level query API classes, like predicates, relation collection, groupby collection but also the Unit of Work classes, are now serializable to XML, and as such passable to e.g. a WCF Service. This is for Adapter only.
Changed
- SourceFieldFinder. The SourceFieldFinder is now a public class so it can be used to traverse entity graphs in user code.
- Better name length clamping in DB2 and Oracle DQEs. Names were already limited to 30 characters or less for DB2 and Oracle, but in some edge case queries with nested derived tables it could be the field inside a derived table was clamped to a shorter name, but a field referencing it wasn't. Name clamping now uses F__hashcodeOfStringToClamp which is not depending on field index anymore.
- The runtime assemblies are now stored all in one folder. In previous versions the runtime library assemblies were stored in different folders, based on the .net version they were for. This is not needed anymore, so all files are stored in one folder.
- DbCommands are now, when possible, created from DbConnection. This makes it easier to add functionality like the miniprofiler to the generated code.
- DataProjectorToDataTable now creates columns from projectors. This change has the advantage that if the resultset to project has 0 rows, the columns in the datatable are still created.
Fixed
- Add auto-type filter if projection contains fields of 1 type only. See: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=21502
- IRetrievalQuery requires a flag to signal no name overwriting required. See: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=21658&StartAtMessage=0
- ObjectGraphUtils uses GetMemberEntityCollections which triggers collection creation on adapter. It now uses less intrusive methods, so it doesn't trigger collection creation.