Breaking Changes- Entity Framework Beta 3
EDM Changes
1. CommandText attribute on Function element in SSDL schema has been changed to a child Element.
Mitigation
If you used the CommandText attribute on Function elements, change it to a Child Element.
Beta 2 Code
<Function Name="InsertProduct" IsComposable="false" CommandText="Insert Products ...">
Beta 3 Code
<Function Name="InsertProduct" IsComposable="false" > <CommandText>Insert Products ...</CommandText>
2. Changed all Enumeration values in Schema Files to have Pascal Casing so that they are consistent.
Mitigation
Change the SchemaFiles to reflect the new values.
Csdl Changes
|
Area |
Beta 2 |
Beta 3 |
|
DateTimeKind |
UTC |
Utc |
|
Mode |
in |
In |
|
Mode |
out |
Out |
|
Mode |
inout |
InOut |
|
ConcurrencyMode |
none |
None |
|
ConcurrencyMode |
fixed |
Fixed |
|
MaxLength |
max |
Max |
Ssdl Changes
|
Area |
Beta 2 |
Beta 3 |
|
DateTimeKind |
UTC |
Utc |
|
Mode |
in |
In |
|
Mode |
out |
Out |
|
Mode |
inout |
InOut |
|
StoreGeneratedPattern |
none |
None |
|
StoreGeneratedPattern |
identity |
Identity |
|
StoreGeneratedPattern |
computed |
Computed |
|
MaxLength |
max |
Max |
ProviderManifest Changes
|
Area |
Beta 2 |
Beta 3 |
|
Mode |
in |
In |
|
Mode |
out |
Out |
|
Mode |
inout |
InOut |
CSMapping Changes
|
Area |
Beta 2 |
Beta 3 |
|
Version |
original |
Original |
|
Version |
current |
Current |
CodeGeneration Changes
|
Area |
Beta 2 |
Beta 3 |
|
Access |
public |
Public |
|
Access |
internal |
Internal |
|
Access |
private |
Private |
|
Getter/Setter |
public |
Public |
|
Getter/Setter |
internal |
Internal |
3. GetMappedPrimitiveType method on MetadataWorkspace and ItemCollection class has been removed.
Beta 2 Code
PrimitiveTypeKind edmType = ((PrimitiveType)
sourceProperty.Type.EdmType).PrimitiveTypeKind;
PrimitiveType sqlType = workspace.GetMappedPrimitiveType(edmType,
DataSpace.SSpace);
Beta 3 Code
TypeUsage edmType = sourceProperty.TypeUsage;
EntityConnection connection = context.Connection as EntityConnection;
DbProviderServices services = DbProviderServices.CreateProviderServices
(connection.StoreConnection);
DbProviderManifest manifest = services.GetProviderManifest
(connection.StoreConnection);
TypeUsage sqlType = manifest.GetStoreType(edmType);
4. StoreItemCollection that is Constructed over SqlConnection needs an Open or Openable connection. Previously a non-null SqlConnection would have worked even if it could not be opened.
Mitigation
If you were previously using a SqlConnection that was not openable and you don't prefer the provider to open a connection, you would need to use a new Constructor added to the StoreItemCollection that takes in DBProviderFactory instead of DBConnection. This would only work if the SSDL file passed into the constructor had a ProviderManifestToken attribute added to the Schema element.
Beta 2 Code
storeItemCollection = new StoreItemCollection( new SqlConnection(), ssdlFilePath);
Beta 3 Code
storeItemCollection = new StoreItemCollection(SqlClientFactory.Instance, ssdlFilePath);
5. Unsigned types have been removed from EDM/CSDL type system.
Mitigation
No mitigation for this.
Entity Services Changes
6. Obtaining the native SQL generated for a given command has changed. EntityCommand - DbProviderServices.CreateCommandDefinition, ObjectQuery.CreateCommandTree() and DbProviderServices.CreateCommandDefinition are no longer available
Mitigation
There is a new, simpler, pattern. Use EntityCommand.ToTraceString() or ObjectQuery.ToTraceString().
Beta 2 Code
string esql = "SELECT VALUE product \n" +
"FROM Northwind.Products AS product\n" +
"WHERE LEFT(product.ProductName, 1) = 'C' \n" +
"ORDER BY product.ProductName";
EntityCommand productsCmd = connection.CreateCommand();
productsCmd.CommandText = esql;
connection.Open();
productsCmd .Prepare();
IServiceProvider serviceProvider = (IServiceProvider)EntityProviderFactory.Instance;
DbProviderServices providerServices = (DbProviderServices)serviceProvider.GetService(typeof(DbProviderServices));
EntityCommandDefinition commandDefinition = (EntityCommandDefinition)providerServices.CreateCommandDefinition(productsCmd );
foreach (string commandText in commandDefinition.MappedCommands)
{
Console.WriteLine(commandText);
}
Beta 3 Code
// For EntityCommand
string esql = "SELECT VALUE product \n" +
"FROM Northwind.Products AS product\n" +
"WHERE LEFT(product.ProductName, 1) = 'C' \n" +
"ORDER BY product.ProductName";
EntityCommand productsCmd = connection.CreateCommand();
productsCmd.CommandText = esql;
connection.Open();
Console.WriteLine(productsCmd.ToTraceString());
// For ObjectQuery
ObjectQuery<Northwind.Product> products = northwind.Products
.Where("LEFT(it.ProductName, 1) = 'C'")
.OrderBy("it.ProductName");
northwind.Connection.Open();
Console.WriteLine(products.ToTraceString());
7. Canonical function Edm.Length() ignores trailing white space when connected to SQL Server (any version).
Mitigation
Previously Edm.Length() was trying to include trailing spaces. Starting with Beta 3 it maps directly to SqlServer.Len() which ignores trailing spaces. Consider trimming trailing white space on literals and properties before sending them down the pipeline.
Beta 2 Code
Edm.Length('abc ')
-- T-SQL: LEN('abc ' + '.') - LEN('.')
-- Returns: 4
Beta 3 Code
Edm.Length('abc ')
-- T-SQL: LEN('abc ')
-- Returns: 3
LINQ to Entities Changes
8. Group By can no longer be applied on a navigation property
Mitigation
Add the key properties of the related entity to the query after the navigation property.
Beta 2 Code
var query = from p in context.Products
group p by p.Category into g
select new
{
CategoryID = g.Key,
AveragePrice = g.Average(p=>p.UnitPrice)
};
Beta 3 Code
var query = from p in context.Products
group p by p.Category.CategoryID into g
select new
{
CategoryID = g.Key,
AveragePrice = g.Average(p=>p.UnitPrice)
};
Object Services Changes
9. ObjectStateManager.GetObjectStateEntry() no longer accepts an entity object instance as a parameter
Mitigation
Pass an EntityKey instead.
Beta 2 Code
var order = context.Orders.First();
var state = context.ObjectStateManager.GetObjectStateEntry(order);
Beta 3 Code
var order = context.Orders.First();
var state = context.ObjectStateManager.GetObjectStateEntry(order.EntityKey);
10. ObjectQuery.First(), -FirstOrDefault(), and -Exists() have been removed.
Mitigation
Use the LINQ to Entities implementation through IQueryable.
Beta 2 Code
Product product = northwind.Products.First();
Beta 3 Code
using System.Linq;
Product product = northwind.Products.First();
11. ObjectQuery.Parameters collection is locked once the query is compiled/executed.
Mitigation
Ability to add or remove paramters to the parameter collection once the query is compiled was an error. Now Entity Framework explicitly throws on such attempts.
Note: values of existing parameters may be changed, and subsequent executions of the query will use the new values.
Beta 2 Code
ObjectQuery<Product> products = northwind.Products
.Where("it.ProductName LIKE @startsWith + '%'")
.OrderBy("it.ProductName");
products.Parameters.Add(new ObjectParameter("startsWith", "C"));
foreach (Northwind.Product product in products)
{
Console.WriteLine("{0,2}: {1}", product.ProductID, product.ProductName);
}
products.Parameters.Add(new ObjectParameter("foo", "ABC"));
// The above statement passes
Beta 3 Code
ObjectQuery<Product> products = northwind.Products
.Where("it.ProductName LIKE @startsWith + '%'")
.OrderBy("it.ProductName");
products.Parameters.Add(new ObjectParameter("startsWith", "C"));
foreach (Northwind.Product product in products)
{
Console.WriteLine("{0,2}: {1}", product.ProductID, product.ProductName);
}
products.Parameters.Add(new ObjectParameter("foo", "ABC"));
// The above statement throws InvalidOperationException
12. EntityKey.EntityKeyValues has changed from ReadOnlyCollection<KeyValuePair<string, object>> to EntityKeyMember[].
Mitigation
An EntityKeyMember is a KeyValuePair that can be serialized using Xml serialization. It contains both a string key name and an object key value.
13. ObjectContext no longer opens a connection during the constructor.
Mitigation
The ObjectContext class no longer opens the underlying EntityConnection as part of the constructor call. As a result, the MetadataWorkspace that is returned from the MetadataWorkspace property will not contain the SSpace and CSSpace metadata immediately. These metadata collections will be available the first time the ObjectContext opens the underlying EntityConnection.
14. EntityKey class no longer implements IXmlSerializable
Mitigation
The EntityKey class is still serializable using the XmlSerializer, but uses public properties rather than an explicit implementation of IXmlSerializable.
15. EntityKey(EntitySet entitySet, IEnumerable<KeyValuePair<string, object>> entityKeyValues) constructor has been removed.
Mitigation
Use an alternative constructor.
Beta 2 Code
EntityKey key = new EntityKey(entitySet, keyValues);
Beta 3 Code
EntityKey key = new EntityKey(entitySet.EntityContainer.Name + "." + entitySet.Name, keyValues)
16. EntityKey(string qualifiedEntitySetName, string[] keyNames, object[] keyvalues) constructor has been removed
Mitigation
Use an alternative constructor such as
Beta 2 Code
EntityKey key = new EntityKey("EC.ES", new string[] {"K1", "K2"}, new object[] {key1, key2});
Beta 3 Code
EntityKey key = new EntityKey("EC.ES", new EntitykeyMember[] {
new EntityKeyMember("K1", key1),
new EntityKeyMember("K2", key2)});
17. ObjectStateManager.GetEntityKey(object) has been removed.
Mitigation
To get an EntityKey for an object instance, call ObjectContext.GetEntityKey(entitySetName, object). This key can then be used to lookup an ObjectStateEntry in the ObjectStateManager to determine if the object is being tracked.
Beta 2 Code
EntityKey key = stateManager.GetEntityKey(object);
Beta 3 Code
EntityKey key = context.GetEntityKey(entitySetName, object);
18. EntityCollection.CollectionChanged event has been renamed to AssociationChanged
Mitigation
Use the AssociationChanged event instead of the CollectionChanged event
Beta 2 Code
collection.CollectionChanged += handler;
Beta 3 Code
collection.AssociationChanged += handler;
19. ObjectQuery IListSource implementation is explicitly implemented.
Mitigation
You will need to cast the ObjectQuery to an IListSource before calling ContainsListCollection property or the GetList method.
Beta 2 Code
IList list = query.GetList();
Beta 3 Code
IList list = ((IListSource)query).GetList();
20. ObjectContext.Refresh no longer takes a params array of objects to refresh.
Mitigation
The overloads for Refresh include one that takes a single object to refresh, as well as one that takes an IEnumerable of objects to refresh.
Beta 2 Code
ctx.Refresh(RefreshMode.ServerWins, o1, o2, o3);
Beta 3 Code
ctx.Refresh(RefreshMode.ServerWins, new object[] {o1, o2, o3});
21. ObjectQuery.GetResultType() requires the user to open the connection.
Mitigation
The GetResultType() call requires that the user have the CSSpace and SSpace metadata collections loaded into the ObjectContext's MetadataWorkspace. To do this, the ObjectContext's connection must have opened at some point. The connection can be forced to open by calling ctx.Connection.Open().
Tools Changes
22. EDMX files created in CTP1 don't always open in CTP2 of the designer
Mitigation
The file format of .edmx files has changed in CTP2. Opening .edmx files created with earlier versions of the designer is not supported.
To resolve this issue:
Recreate the .edmx file in CTP2 of the designer.
23. Build error when projects with .edmx files created in Visual Studio Beta 2 and EDM Designer CTP 1 are rebuilt in Visual Studio 2008 RTM
Mitigation
Projects with .edmx files created in earlier CTPs had a reference to EdmxDeploy.exe in the project post-build event. Building such projects in VS 2008 RTM causes a build failure with a message that EdmxDeploy.exe cannot be found.
To resolve this issue:
The functionality provided by EdmxDeploy.exe is now available in the EntityDeploy MSBUILD task. Modify the post-build event in project properties and remove the reference to EdmxDeploy.exe