Entity Framework Breaking Changes - Visual Studio 2008 & .NET 3.5 SP1 Beta

For the release of SP1 Beta, several breaking changes were made to the Entity Framework. Below is a description of these changes and a mitigation for resolving the breaking change against previous releases.

Schema Changes( covers CSDL, SSDL and ProviderManifest Xml formats)

1. Attribute name for Default changed to Default values

Beta 3 Schema

  <Property Name="tempval" Type="Int32" Default="12" />

SP1 Beta Schema

  <Property Name="tempval" Type="Int32" DefaultValue="12" />

Affected Schemas

        CSDL, SSDL and provider manifest schemas which used Defaults.

Mitigation

Either regenerate the schema files using the tools or change the files manually based on the information above.

2. PreserveSeconds facet has been removed

Affected Schemas

        SSDL schemas which used PreserveSeconds facet.

Mitigation

There is no mitigation. We were not really using this facet and so we decided to remove it.

 

3. DateTimeKind facet has been removed

Affected Schemas

        CSDL and SSDL schemas which used DateTimeKind facet.

Mitigation

There is no mitigation. We were not really using this facet and so we decided to remove it.

4. In SSDL schema, ProviderManifestToken values for Sql Provider changed and there is a new required attribute called “Provider”.

Affected Schemas

All SSDL schemas that go against Sql Server Database.

Beta 3 Schema Fragment

<Schema Namespace="SchemaNS" ProviderManifestToken="09.00" xmlns="..">

SP1 Beta Schema

<Schema Namespace="SchemaNS" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns="..">

Mitigation

Either regenerate the schema files using the tools or change the files manually based on the information above.

Object Services Changes

1. Removing StructuralObject.SetValidValue methods

The following SetValidValue methods on the StructuralObject class were removed:
protected internal static decimal SetValidValue(decimal value, int precision, int scale)

protected internal static Nullable<decimal>

SetValidValue(Nullable<decimal> value, int precision, int scale)
protected internal static string

SetValidValue(string value, bool isNullable, int maximumLength)
protected internal static Byte[]

SetValidValue(Byte[] value, bool isNullable, int maximumLength)
protected internal static Nullable<DateTime>

SetValidValue(Nullable<DateTime> value, DateTimeKind kind)
protected internal static DateTime

SetValidValue(DateTime value, DateTimeKind kind)

Mitigation

You can re-run code generation to get files without these method calls in place.

2. Renaming ObjectContext.QueryTimeout to CommandTimeout

Beta 3 Code

ObjectContext context = new ObjectContext(“connectionString”);

context.QueryTimeout = 30;

 

SP1 Beta Code

ObjectContext context = new ObjectContext(“connectionString”);

context.CommandTimeout = 30;

 

Mitigation

Rename the property.

3. Attempt to access connection object of ObjectContext after Dispose is called results in ObjectDisposedException being thrown.

Mitigation

The “disposed” ObjectContext can still be used as long as the caller does not directly or indirectly invoke an operation that requires a connection. A new ObjectContext will need to be created if access to the underlying store through an ObjectContext is required.

 

4. IRelatedEnd.Add allows repeated calls with the same parameter instance

IRelatedEnd.Add, EntityCollection.Add, and EntityReference.Value will no longer throw an exception if the same instance is added to the collection or reference more than once.

Beta 3 Code

Order o = Order.CreateOrder(1);

customer.Orders.Add(o);

// This line will throw

customer.Orders.Add(o);

SP1 Beta Code

Order o = Orders.CreateOrder(1);
customer.Orders.Add(o);
// This line will NOT throw
customer.Orders.Add(o);

 

//-- To get the original behavior:

Order o = Orders.CreateOrder(1);
customer.Orders.Add(o);
if(customer.Orders.Contains(o))

{

    throw new InvalidOperationException(...);

}

customer.Orders.Add(o);

Mitigation

To throw an exception in this case, you can decorate the call to Add or the Value setter to check if the collection or reference already contains the value you are adding.

5. IRelatedEnd.Remove and EntityCollection.Remove returns true or false rather than throwing an exception

The Remove API of EntityCollection and RelatedEnd has changed to return true if the item was successfully removed from the related end or collection, and false if the item could not be found for the remove. This more closely matches the .NET collection remove functionality.

Beta 3 Code

try

{

   customer.Orders.Remove(o);

}

catch(Exception e)

{

  //

}

SP1 Beta Code

if(!customer.Orders.Remove(o))

{

  // could not find the item

}

Mitigation

To get an exception, check the return value of Remove and throw an appropriate Exception.

Providers

1. InformationSchema Conceptual model used for Tools changed

Beta 3 Code

            SELECT

            t.Catalog

        , t.Schema

        , t.Name

        , c.Name

        , c.Ordinal

        , c.IsNullable

        , c.TypeName

        , c.MaxLength

        , c.Precision

         , c.DateTimePrecision

        , c.Scale

        , c.IsIdentity

        , c.IsStoreGenerated

        , c.PrimaryKey.Ordinal

           FROM

               SchemaInformation.Tables as t

                 cross apply

               t.Columns as c

           ORDER BY

               t.Schema

           , t.Name

           , c.Ordinal

SP1 Beta Code

             SELECT

                 t.CatalogName

             , t.SchemaName

             , t.Name

             , t.ColumnName

             , t.Ordinal

             , t.IsNullable

             , t.TypeName

             , t.MaxLength

             , t.Precision

             , t.DateTimePrecision

             , t.Scale

             , t.IsIdentity

             , t.IsStoreGenerated

             , CASE WHEN pk.IsPrimaryKey IS NULL THEN false ELSE pk.IsPrimaryKey END as IsPrimaryKey

           FROM (

             SELECT

                 t.CatalogName

             , t.SchemaName

             , t.Name

             , c.Id as ColumnId

             , c.Name as ColumnName

             , c.Ordinal

             , c.IsNullable

             , c.ColumnType.TypeName as TypeName

          , c.ColumnType.MaxLength as MaxLength

             , c.ColumnType.Precision as Precision

             , c.ColumnType.DateTimePrecision as DateTimePrecision

             , c.ColumnType.Scale as Scale

             , c.IsIdentity

             , c.IsStoreGenerated

             FROM

                 SchemaInformation.Tables as t

                 cross apply

                 t.Columns as c ) as t

           LEFT OUTER JOIN (

             SELECT

                 true as IsPrimaryKey

               , pkc.Id

             FROM

                 OfType(SchemaInformation.TableConstraints, Store.PrimaryKeyConstraint) as pk

                 CROSS APPLY pk.Columns as pkc) as pk

           ON t.ColumnId = pk.Id

           ORDER BY

               t.SchemaName

           , t.Name

           , t.Ordinal

 

Mitigation

All the same infomation is available, but in a different shape so most queries will need to be re written

Metadata

 

1. StoreItemCollection public constructor changes

You are no longer able to create an "Empty" StoreItemCollection, or a StoreItemCollection with only PrimitiveTypes in it. If you need the Store PrimitiveTypes, you will need to find them in the DbProviderManifest.

Beta 3 Code

StoreItemCollection itemCollection = new StoreItemCollection(connection, file1, file2);

SP1 Beta Code

StoreItemCollection itemCollection = new StoreItemCollection(file1, file2);

Mitigation

Remove the DbConnection or DbProviderFactory from your call to the constructor of StoreItemCollection

2. Changed the hash computation used in pre-generated views to ignore the facets( except for Nullable facet).

View Generation was changed to not take these facets into account so these values are not used in the hash generation.

Mitigation

Please regenerate the generated views source file using the “EdmGen /mode:ViewGeneration …”.