New features in Entity Framework impacting providers

 


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.


 

Providers for Entity Framework 3.5 will work unmodified against Entity Framework 4.0. Also, most of the features and improvements introduced in Entity Framework 4.0 will just work against an Entity Framework 3.5 provider. However, there are several features that require provider changes to be enabled. Below is a list of these features along with short description of the changes required to enable them.

New features in Entity Framework Runtime impacting providers

New EDM (Canonical) Functions

In Entity Framework 3.5 there is a set of EDM (canonical) functions, which are defined by the Entity Framework and should be supported by all store providers. In Entity Framework 4.0 we are expanding that set by adding a number of new string, aggregate, mathematical, and date/time functions. Providers would need to add support for these new functions, listed below.

Date/Time functions

CreateDateTime(year, month, day, hour, minute, second)

CreateDateTimeOffset(year, month, day, hour, minute, second, tzoffset)

CreateTime(hour, minute, second)

DayOfYear(expression)

TruncateTime(expression)

AddYears(expression, number)

AddMonths(expression, number)

AddDays(expression, number)

AddHours(expression, number)

AddMinutes(expression, number)

AddSeconds(expression, number)

AddMilliseconds(expression, number)

AddMicroseconds(expression, number)

AddNanoseconds(expression, number)

DiffYears(startExpression, endExpression)

DiffMonths(startExpression, endExpression)

DiffDays(startExpression, endExpression)

DiffHours(startExpression, endExpression)

DiffMinutes(startExpression, endExpression)

DiffSeconds(startExpression, endExpression)

DiffMilliseconds(startExpression, endExpression)

DiffMicroseconds(startExpression, endExpression)

DiffNanoseconds(startExpression, endExpression)

Math Functions

Power(value, exponent)

Truncate(value, digits)

Round(value, digits)

Aggregate functions

StDevP(expression)

Var (expression)

VarP (expression)

String functions

Contains(string, target)

StartsWith(string, target)

EndsWith(string, target)

Exposing provider functions in LINQ To Entities ()

Entity Framework 3.5 customers preferring to write their queries using LINQ often hit a limitation on the range of functions and query patterns supported in LINQ to Entities. To address that issue, we are providing an extensibility mechanism that can be used to map CLR methods to provider and to EDM functions.

The basis of the extensibility mechanism is a new method-level attribute that carry function mapping information. Here is the basic signature of the attribute’s constructor:

public EdmFunctionAttribute(string namespaceName, string functionName)

The namespaceName parameter indicates the namespace for the function in metadata (i.e. “EDM” or “SQLSERVER”, or other store provider namespace). The functionName parameter takes the name of the function itself.

We encourage providers to expose classes that represent their store functions, so that when their provider is used they are readily available via LINQ to Entities. Here are some recommendations with regards to which functions to expose and how:

Which functions to expose?

  • These that provide functionality not already provided via the base class library functions supported by LINQ to Entities or the EDM functions.

Overloads – Provide enough for pleasant user experience

  • Specify the scalar arguments and return types as nullable
  • Provide overloads for nullable and non-nullable collection element for collection arguments

Proxies Implementation

  • Trigger direct evaluation over the input ObjectQuery for methods taking collection arguments
  • Throw NotSupportedException in all other cases

Example:

 

 [EdmFunction(“SampleSqlServer", "CHECKSUM_AGG")] 
 public static Int32? ChecksumAggregate( IEnumerable<Int32> arg) { 
 ObjectQuery<Int32> objectQuerySource = arg as ObjectQuery<Int32>; 
 if (objectQuerySource != null) { 
 return ((IQueryable)objectQuerySource).Provider
 .Execute<Int32?>(Expression.Call((MethodInfo)MethodInfo
 .GetCurrentMethod(),Expression.Constant(arg))); 
 } 
 throw new NotSupportedException("This function can only be invoked from LINQ 
                            to Entities."); 
 } 
 [EdmFunction(“SampleSqlServer", "CHECKSUM_AGG")]
         public static Int32? ChecksumAggregate( IEnumerable<Int32?> arg)  { 
        { …. } 
Translating String.StartsWith, String.EndsWith and String.Contains to LIKE in LINQ to Entities

In Entity Framework 3.5, in LINQ to Entities we provided support for the String.StartsWith, String.EndsWith and String.Contains and we translated them to canonical functions in the following way:

Boolean String.Contains(String value) -> IndexOf(this, value) > 0

Boolean String.EndsWith(String value) -> Right(this, length(value)) = value

Boolean String.StartsWith(String value) -> IndexOf(this, value) = 1                       

However, due to the fact that these translations result in inability to utilize indexes on the tested string on some providers and that users found the resulting SQL more difficult to read, we are providing an option to translate these into DbLikeExpression, i.e:

Boolean String.Contains(String value) -> DbLikeExpression(this, ‘%’ + value’ + ‘%’, escapeCharacter)

Boolean String.EndsWith(String value) -> DbLikeExpression(this, ‘%’ + value’, escapeCharacter)

Boolean String.StartsWith(String value) -> DbLikeExpression(this, value’ + ‘%’’, escapeCharacter)

Here, value’ is the equivalent of value but with the wildcard characters and the escape character escaped, and escapeCharacter is the escape character. This translation only happens if value is a constant or a parameter. 

Because different providers may have different wildcard characters, in order for this translation to happen provider writers need to override and provide implementations of the following methods that have been introduced in DbProviderManifest:

public virtual bool SupportsEscapingLikeArgument(out char escapeCharacter)

and

public virtual string EscapeLikeArgument(string argument)

The default implementation of SupportsEscapingLikeArgument returns false, thus if provider writers choose to not override these methods, they will still continue to get the old translations of these functions.

Please note that this feature is not any public release yet, but it will be available in .NET 4.0.

New Features in Entity Designer Impacting Providers

Model First

In Visual Studio 2010 the designer can generate mappings, storage model, and database DDL from a conceptual model. This feature is called “Model First.” In order to make this feature highly customizable, it is implemented using a Workflow Foundation (WF) workflow that users can replace. The workflow contains two activities: One which generates MSL and SSDL, and another which generates DDL.

DDL generation is done by a T4 template which processes the SSDL generated by the previous workflow activity. Providers who wish to allow users to generate DDL for databases other than SQL Server will need to install a T4 DDL generation template in:

%localappdata%\Microsoft\[AppId]\10.0\Extensions\Microsoft\Entity Framework Tools\DBGen

Where [AppId] signifies either VisualStudio, VBExpress, VCSExpress, or VNSExpress depending on what SKU the user is using at the moment. Note that when searching for templates, the Entity Framework Designer does not do recursive searches. 
Templates from this path have “(User)” post-pended to their name.

For reference, built-in templates are installed in:

%programFiles%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen

Templates from this path have “(VS)” post-pended to their name.

Here is a screenshot. In this case, a template called “CustomDDL.tt” was added to the “(User)” path referenced above. (In the case of this specific machine, that path was D:\Documents and Settings\SQLCL02\Local Settings\Application Data\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Entity Framework Tools\DBGen)

 

blog1

The same rules also apply to workflows. In this screenshot, we added a workflow called “CustomStrategy.xaml” to the “(User)” directory:

blog1

In both cases, there is no need to restart VS, as the templates and workflows show up immediately.

Please note that this feature is not any public release yet, but it will be available in Visual Studio 2010.

Thank you!

Kati Iceva
Software Development Engineer, Entity Framework

Noam Ben-Ami
Program Manager, Entity Designer