EF Designer now supports EF6

Some time ago I showed how to hack the EF Designer shipped with Visual Studio 2012 to work with EF6. Those hacks should be no longer needed – last week we shipped Entity Framework 6 Beta1 which for the first time contains not only EF6 runtime but also contains tooling. The new EF Designer works with Visual Studio 2012 and replaces the designer that was originally shipped with Visual Studio 2012. Almost all the work we did was about adding support for EF6 – being able to handle new metadata types, using the new provider model, creating EF6 specific T4 templates etc. This work has not been completed yet and some scenarios like support for EF6 on .NET Framework 4 or using non-SqlServer (or SqlServerCE) providers when using EF6 are still not enabled but if you want to use model first/database first workflows with EF6 the Beta version is currently your best option. Note that even though this release is mostly about adding support for EF6 we are not abandoning EF5. For EF5 the EF Designer Beta 1 version supports all the scenarios that were supported by the previous versions. You choose the target version of Entity Framework in the wizard when adding a new model to your project (note that in some cases the choice is limited – e.g. if your project already has a reference to System.Data.Entity.dll you won’t be able to select EF6).

It’s not a June CTP kind of thing
EF6 runtime is no longer shipped as part of the .NET Framework and we did not have to do hacks we had to do when shipping tooling in June 2011 CTP. It means that it is easy to install the EF Designer Beta 1 but it is also easy to uninstall it and go back to the original designer shipped with Visual Studio 2012 – just go to Programs and Features, uninstall the new designer and repair Visual Studio and things should work as they did before.

How to get it?
Just go to the download center and install the msi.

We want your feedback
Since the new EF Designer is easy to install and uninstall and it supports all the scenarios supported by the old one I would like to encourage everyone to try it out and let us know about your experience (and issues). This is only a Beta version and we already know it has some rough edges but it may also have bugs we don’t not know about yet. Try it out and if you see something start a new discussion or create a new work item.

EF6 CodeFirst View Generation T4 Template for C# updated for EF6 Beta1

Entity Framework 6 Beta 1 has shipped. The good news is that among (many) others it contains a few changes to view generation. There is now a public API on the StorageMappingItemCollection type that can return views for a given StorageMappingItemCollection instance. The bad news is that some of the changes we introduced in this area in the Beta version are breaking. This means that views created with the EF6 CodeFirst View Generation T4 Template for C# I created for the EF6 Alpha will no longer work with the Beta version and need to be recreated. The main changes (apart from adding the public API) to view generation in Beta are:

Because of the above breaking changes I updated the EF6 CodeFirst View Generation T4 Template for C# to work with EF6 Beta 1. Note that the new version uses the new public API for view generation and therefore it requires that your project has a reference to the EntityFramework.dll shipped with EF6 Beta 1. Also, you cannot generate views with the new version and re-use them in an EF6 Alpha project.
Installation steps have not changed comparing to the previous version and you can found them in this post. You shall not have to uninstall the previous version – the new vsix should replace the old one.

Entity Framework 6 on Mono

I had been wanting to try Entity Framework 6 with Mono for a long time and finally after a check-in I made on Friday I was able to spare some time to do this. I decided to go with MySQL and dotConnect for MySQL from Devart. After skimming the tutorial on using Devart’s providers with EF6 I opened Visual Studio 2012, created a new project, installed the EF6 alpha3 package from NuGet and thought I was almost done. The only problem was that the dead simple (one entity) EF6 based app I created did not work. I did not expect the exception I got and quickly realized why the tutorial I was following started with “Entity Framework 6 Alpha 2 support is implemented…”. Things got a little better when I went back from EF6 Alpha 3 to EF6 Alpha 2 but still did not work. I found that I was missing one of the dlls and then that I used wrong revision number in the version of the provider assemblies (interestingly the version of the assembly containing the provider factory was 7.6.217.0 while the version of the assembly containing provider services was 7.6.217.6 – I expected both assemblies to have the same version). The last time I used MySQL was… some time ago (OK, it was in the 20th century) and it was the first time I used it with Code First (kinda obvious). Even after setting all the versions correctly the app still did not want to run. I was able to get the edmx file with the EdmxWriter (which is a good sign meaning that the provider is configured correctly and working) but then the app would die because it could not create the database. After a quick search I found that I need to create an empty database using MySQL command prompt and then EF should be able to add tables to this database. Indeed – after I created the empty database that app did not throw and I was able to add entities to the database and then read them. With this I was ready to move to the Mono world. So, I installed the latest version of Mono and started playing a little bit with it. mcs.exe (the compiler) worked just fine. However since I could build my app with Visual Studio and ran it using mono.exe I decided not to use the mcs.exe. Unfortunately the app would not quite work. It would start and then throw System.Configuration.ConfigurationErrorsException: Failed to find or load the registered .Net Framework Data Provider .... Which basically means that the ADO.NET/EF provider I used was not registered. I think the reason was that I installed Mono after I installed the provider and therefore the entry in the machine.config was missing. I added the following entry:

  <system.data>
    <DbProviderFactories>
      <remove invariant="Devart.Data.MySql" />
      <add name="dotConnect for MySQL" invariant="Devart.Data.MySql" 
           description="Devart dotConnect for MySQL" 
           type="Devart.Data.MySql.MySqlProviderFactory, Devart.Data.MySql, Version=7.6.217.0, Culture=neutral, PublicKeyToken=09af7300eec23701" />
    </DbProviderFactories>
  </system.data>

to my app.config file and I was able to get a little bit further. (Just in case – you can just add the “add” line from the above to the Mono’s machine.config in the provider section and it should work as well). Now when I ran my app I got this:

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.EntityKeyElement.Validate () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.SchemaEntityType.Validate () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.Schema.Validate () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.Schema.ValidateSchema () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.SchemaManager.ParseAndValidate (IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, SchemaDataModelOption dataModel, System.Data.Entity.Core.EntityModel.SchemaObjectModel.AttributeValueNotification providerNotification, System.Data.Entity.Core.EntityModel.SchemaObjectModel.AttributeValueNotification providerManifestTokenNotification, System.Data.Entity.Core.EntityModel.SchemaObjectModel.ProviderManifestNeeded providerManifestNeeded, IList`1&amp; schemaCollection) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection+Loader.LoadItems (IEnumerable`1 xmlReaders, IEnumerable`1sourceFilePaths) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection+Loader..ctor (IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, Boolean throwOnError) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection.Init (IEnumerable`1 xmlReaders, IEnumerable`1 filePaths, Boolean throwOnError, System.Data.Entity.Core.Common.DbProviderManifest&amp; providerManifest, System.Data.Common.DbProviderFactory&amp; providerFactory, System.String&amp; providerManifestToken, System.Data.Entity.Core.Common.Utils.Memoizer`2&amp; cachedCTypeFunction) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection..ctor (IEnumerable`1 xmlReaders) [0x00000] in :0
  at System.Data.Entity.Utilities.XDocumentExtensions.GetStoreItemCollection (System.Xml.Linq.XDocument model, System.Data.Entity.Infrastructure.DbProviderInfo&amp; providerInfo) [0x00000] in :0
  at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff (System.Xml.Linq.XDocument sourceModel, System.Xml.Linq.XDocument targetModel, Nullable`1 includeSystemOperations) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.ModelMatches (System.Xml.Linq.XDocument model) [0x00000] in :0
  at System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel (System.Data.Entity.Internal.InternalContext internalContext, System.Data.Entity.Internal.ModelHashCalculator modelHashCalculator, Boolean throwIfNoMetadata) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.CompatibleWithModel (Boolean throwIfNoMetadata) [0x00000] in :0
  at System.Data.Entity.Database.CompatibleWithModel (Boolean throwIfNoMetadata) [0x00000] in :0
  at System.Data.Entity.CreateDatabaseIfNotExists`1[System.Data.Entity.DbContext].InitializeDatabase (System.Data.Entity.DbContext context) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext+c__DisplayClassc`1[EF6MySqlTest.SimpleContext].b__b () [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.PerformInitializationAction (System.Action action) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization () [0x00000] in :0
  at System.Data.Entity.Internal.LazyInternalContext.b__4 (System.Data.Entity.Internal.InternalContext c) [0x00000] in :0
  at System.Data.Entity.Internal.RetryAction`1[System.Data.Entity.Internal.InternalContext].PerformAction (System.Data.Entity.Internal.InternalContext input) [0x00000] in :0
[ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.EntityKeyElement.Validate () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.SchemaEntityType.Validate () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.Schema.Validate () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.Schema.ValidateSchema () [0x00000] in :0
  at System.Data.Entity.Core.EntityModel.SchemaObjectModel.SchemaManager.ParseAndValidate (IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, SchemaDataModelOption dataModel, System.Data.Entity.Core.EntityModel.SchemaObjectModel.AttributeValueNotification providerNotification, System.Data.Entity.Core.EntityModel.SchemaObjectModel.AttributeValueNotification providerManifestTokenNotification, System.Data.Entity.Core.EntityModel.SchemaObjectModel.ProviderManifestNeeded providerManifestNeeded, IList`1&amp; schemaCollection) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection+Loader.LoadItems (IEnumerable`1 xmlReaders, IEnumerable`1sourceFilePaths) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection+Loader..ctor (IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, Boolean throwOnError) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection.Init (IEnumerable`1 xmlReaders, IEnumerable`1 filePaths, Boolean throwOnError, System.Data.Entity.Core.Common.DbProviderManifest&amp; providerManifest, System.Data.Common.DbProviderFactory&amp; providerFactory, System.String&amp; providerManifestToken, System.Data.Entity.Core.Common.Utils.Memoizer`2&amp; cachedCTypeFunction) [0x00000] in :0
  at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection..ctor (IEnumerable`1 xmlReaders) [0x00000] in :0
  at System.Data.Entity.Utilities.XDocumentExtensions.GetStoreItemCollection (System.Xml.Linq.XDocument model, System.Data.Entity.Infrastructure.DbProviderInfo&amp; providerInfo) [0x00000] in :0
  at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff (System.Xml.Linq.XDocument sourceModel, System.Xml.Linq.XDocument targetModel, Nullable`1 includeSystemOperations) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.ModelMatches (System.Xml.Linq.XDocument model) [0x00000] in :0
  at System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel (System.Data.Entity.Internal.InternalContext internalContext, System.Data.Entity.Internal.ModelHashCalculator modelHashCalculator, Boolean throwIfNoMetadata) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.CompatibleWithModel (Boolean throwIfNoMetadata) [0x00000] in :0
  at System.Data.Entity.Database.CompatibleWithModel (Boolean throwIfNoMetadata) [0x00000] in :0
  at System.Data.Entity.CreateDatabaseIfNotExists`1[System.Data.Entity.DbContext].InitializeDatabase (System.Data.Entity.DbContext context) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext+c__DisplayClassc`1[EF6MySqlTest.SimpleContext].b__b () [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.PerformInitializationAction (System.Action action) [0x00000] in :0
  at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization () [0x00000] in :0
  at System.Data.Entity.Internal.LazyInternalContext.b__4 (System.Data.Entity.Internal.InternalContext c) [0x00000] in :0
  at System.Data.Entity.Internal.RetryAction`1[System.Data.Entity.Internal.InternalContext].PerformAction (System.Data.Entity.Internal.InternalContext input) [0x00000] in :0

WTF? The same app worked just fine on .NET Framework! Obviously there was a bug somewhere but where? Mono? EF? .NET Framework? I followed the advice given by John Robins from Wintellect (http://www.wintellect.com/cs/blogs/jrobbins/default.aspx) during the “Debugging Windows Applications” training I took (too) many years ago and prayed that the bug was in the code base I own (because “in this case you can fix it”). I looked at some tutorials on debugging Mono apps but quickly felt it was too much to learn. Then I installed WinDbg but without symbols I could see only this:

ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0022f5ec 76ccbbf7 00000000 77e8f3b0 ffffffff ntdll!KiFastSystemCallRet
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\msvcrt.dll - 
0022f600 758a36dc 00000001 0022f644 758a3372 kernel32!ExitProcess+0x15
0022f60c 758a3372 00000001 172bd79c 016b6698 msvcrt!exit+0x32
0022f644 758a36bb 00000001 00000000 00000000 msvcrt!dup+0x2a9
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mono-3.0.9\bin\mono-2.0.dll - 
0022f658 65a62b3a 00000001 65bba06c 0546e928 msvcrt!exit+0x11
0022f678 65a61fe6 05af88c0 016b6698 00000000 mono_2_0!mono_invoke_unhandled_exception_hook+0x6a
0022f7e8 65aa7aba 00000000 00000000 00000000 mono_2_0!mono_print_thread_dump_from_ctx+0xaa6
0022f898 01550e8f 0022f8b0 05af88c0 03cd75ac mono_2_0!mono_x86_throw_exception+0xca
0022f968 03cd6a64 03d6f230 01c53cc0 03ee0d58 0x1550e8f
0022f9a8 03cd6968 01c53cc0 03ee0d90 0022f9bc 0x3cd6a64
0022f9c8 01bc19f5 01c53cc0 02b8e090 0022f9dc 0x3cd6968
0022f9e8 01bc1984 01c53cc0 02b8e090 0022f9fc 0x1bc19f5
0022fa08 01bc1935 01c53cc0 00538df0 0022fa1c 0x1bc1984
0022fa28 01bc18c5 01c593c0 02b8e090 0022fa3c 0x1bc1935
0022fa48 01bc17be 01c593c0 016bd7a8 0022fa5c 0x1bc18c5
0022fa68 01bc1740 01c593c0 02bc38f8 00000004 0x1bc17be
0022faa8 01bc1654 01c593c0 02b8e060 0022fabc 0x1bc1740
0022fba8 65b5340a 002c73d8 00000001 0022fbf8 0x1bc1654
0022fbb8 659cc21c 00000000 0022fc38 00000000 mono_2_0!mono_runtime_class_init+0x1a
0022fbf8 65b52e42 002c81b0 00000000 0022fc38 mono_2_0!mono_jit_compile_method+0x10c
0022fc18 65b55682 002c81b0 00000000 0022fc38 mono_2_0!mono_runtime_invoke+0x42
0022fc48 65a386b2 002c81b0 00539e00 00000000 mono_2_0!mono_runtime_exec_main+0xd2
*** ERROR: Module load completed but symbols could not be loaded for image00400000
0022fec8 004014bd 00000002 002c1710 00000000 mono_2_0!mono_main+0x1562
0022ff28 004010bb 00000002 002c16e8 002c1bb8 image00400000+0x14bd
0022ff68 004012a8 00000001 00000000 00000000 image00400000+0x10bb
0022ff88 76cbed6c 7ffdd000 0022ffd4 7701377b image00400000+0x12a8
0022ff94 7701377b 7ffdd000 7e6b10f1 00000000 kernel32!BaseThreadInitThunk+0x12
0022ffd4 7701374e 00401290 7ffdd000 00000000 ntdll!RtlInitializeExceptionChain+0xef
0022ffec 00000000 00401290 7ffdd000 00000000 ntdll!RtlInitializeExceptionChain+0xc2

Maybe there are people on this planet who can make sense out of it but I am not there yet. Without symbols I could do not much. So, I ended up sync’ing my source to the changeset around the date we shipped (git reset --hard 9a52aa5f) and this time WinDbg showed this:

This should never be null, since if we were not able to resolve, we should have never reached to this point
---- Assert Long Message ----
   at System.Diagnostics.DefaultTraceListener.Fail(System.String message, System.String detailMessage)
   at System.Diagnostics.TraceListener.Fail(System.String message)
   at System.Diagnostics.DefaultTraceListener.Fail(System.String message)
   at System.Diagnostics.TraceImpl.Fail(System.String message)
   at System.Diagnostics.TraceImpl.Assert(Boolean condition, System.String message)
   at System.Diagnostics.Debug.Assert(Boolean condition, System.String message)
   at System.Data.Entity.Core.EntityModel.SchemaObjectModel.EntityKeyElement.Validate()
   at System.Data.Entity.Core.EntityModel.SchemaObjectModel.SchemaEntityType.Validate()
   at System.Data.Entity.Core.EntityModel.SchemaObjectModel.Schema.Validate()
   at System.Data.Entity.Core.EntityModel.SchemaObjectModel.Schema.ValidateSchema()
   at System.Data.Entity.Core.EntityModel.SchemaObjectModel.SchemaManager.ParseAndValidate(IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, SchemaDataModelOption dataModel, System.Data.Entity.Core.EntityModel.SchemaObjectModel.AttributeValueNotification providerNotification, System.Data.Entity.Core.EntityModel.SchemaObjectModel.AttributeValueNotification providerManifestTokenNotification, System.Data.Entity.Core.EntityModel.SchemaObjectModel.ProviderManifestNeeded providerManifestNeeded, IList`1 ByRef schemaCollection)
   at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection+Loader.LoadItems(IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths)
   at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection+Loader..ctor(IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, Boolean throwOnError)
   at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection.Init(IEnumerable`1 xmlReaders, IEnumerable`1 filePaths, Boolean throwOnError, System.Data.Entity.Core.Common.DbProviderManifest ByRef providerManifest, System.Data.Common.DbProviderFactory ByRef providerFactory, System.String ByRef providerManifestToken, System.Data.Entity.Core.Common.Utils.Memoizer`2 ByRef cachedCTypeFunction)
   at System.Data.Entity.Core.Metadata.Edm.StoreItemCollection..ctor(IEnumerable`1 xmlReaders)
   at System.Data.Entity.Utilities.XDocumentExtensions.GetStoreItemCollection(System.Xml.Linq.XDocument model, System.Data.Entity.Infrastructure.DbProviderInfo ByRef providerInfo)
   at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff(System.Xml.Linq.XDocument sourceModel, System.Xml.Linq.XDocument targetModel, Nullable`1 includeSystemOperations)
   at System.Data.Entity.Internal.InternalContext.ModelMatches(System.Xml.Linq.XDocument model)
   at System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel(System.Data.Entity.Internal.InternalContext internalContext, System.Data.Entity.Internal.ModelHashCalculator modelHashCalculator, Boolean throwIfNoMetadata)
   at System.Data.Entity.Internal.InternalContext.CompatibleWithModel(Boolean throwIfNoMetadata)
   at System.Data.Entity.Database.CompatibleWithModel(Boolean throwIfNoMetadata)
   at System.Data.Entity.CreateDatabaseIfNotExists`1[[System.Data.Entity.DbContext, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].InitializeDatabase(System.Data.Entity.DbContext context)
   at System.Data.Entity.Internal.InternalContext+c__DisplayClassc`1[[EF6MySqlTest.SimpleContext, EF6MySqlTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].b__b()
   at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(System.Action action)
   at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
   at System.Data.Entity.Internal.LazyInternalContext.b__4(System.Data.Entity.Internal.InternalContext c)
   at System.Data.Entity.Internal.RetryAction`1[[System.Data.Entity.Internal.InternalContext, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].PerformAction(System.Data.Entity.Internal.InternalContext input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(System.Action`1 action)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
   at System.Data.Entity.Internal.InternalContext.Initialize()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(System.Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1[[EF6MySqlTest.Customer, EF6MySqlTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1[[EF6MySqlTest.Customer, EF6MySqlTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].get_InternalContext()
   at System.Data.Entity.Internal.Linq.InternalSet`1[[EF6MySqlTest.Customer, EF6MySqlTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].ActOnSet(System.Action action, EntityState newState, System.Object entity, System.String methodName)
   at System.Data.Entity.Internal.Linq.InternalSet`1[[EF6MySqlTest.Customer, EF6MySqlTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].Add(System.Object entity)
   at System.Data.Entity.DbSet`1[[EF6MySqlTest.Customer, EF6MySqlTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].Add(EF6MySqlTest.Customer entity)
   at EF6MySqlTest.Program.Main(System.String[] args)

Apparently my prayer was heard and this line proves it: at System.Diagnostics.Debug.Assert(Boolean condition, System.String message). This is an Assert in the EF code, so looks like a bug in the EF. After looking at the EntityKeyElement.Validate method I could easily find the Assert:

Debug.Assert(
    property != null,
    "This should never be null, since if we were not able to resolve, we should have never reached to this point");

This was a good find (bug filed: https://entityframework.codeplex.com/workitem/1038) but now – how this could have happened? After poking around and using less than scientific methods to debug this I finally concluded that the error is in the invalid SSDL file stored in the __MigrationHistory table. Here is the most interesting fragment:

<EntityType Name=""HistoryRow"" p5:IsSystem=""true"" xmlns:p5=""http://schemas.microsoft.com/ado/2012/10/edm/migrations"">
  <Key p5:IsSystem=""true"">
    <PropertyRef Name=""MigrationId"" p5:IsSystem=""true"" />
    <PropertyRef Name=""ContextKey"" p5:IsSystem=""true"" />
  </Key>
  <Property Name=""MigrationId"" Type=""varchar"" MaxLength=""255"" Nullable=""false"" p5:IsSystem=""true"" />
  <Property Name=""ContextKey"" Type=""varchar"" MaxLength=""512"" Nullable=""false"" p5:IsSystem=""true"" />
  <Property Name=""Model"" Type=""longblob"" Nullable=""false"" p5:IsSystem=""true"" />
  <Property Name=""ProductVersion"" Type=""varchar"" MaxLength=""32"" Nullable=""false"" p5:IsSystem=""true"" />
</EntityType>

It does not look unusual but according to the schema for the SSDL the Key element must not have any attributes (be it in empty or non-empty namespace). Why this thing worked on the .NET Framework and not on Mono? Apparently the Xsd validation in Mono works a bit differently than on the .NET Framework. When processing PropertyRef elements the Xsd validator on .NET Framework reported they were valid whereas Mono claims they are not. I am not sure who is right in this case and, honestly, I don’t care too much. The major bug is in the EF – we should not produce invalid SSDL artifacts (bug filed: https://entityframework.codeplex.com/workitem/1038). This can be fixed either by not writing the {http://schemas.microsoft.com/ado/2012/10/edm/migrations}IsSystem attribute or by allowing attributes in non-empty and non-EF schema on the element. Since I already had a bootleg of entityframework.dll (and I believe the bug is actually in the schema for SSDL) I decided to fix the schema. In the System.Data.Resources.SSDLSchema_3.xsd file I changed the TEntityKeyElement to look like this (added the xs:anyAttribute line):

<xs:complexType name="TEntityKeyElement">
  <xs:sequence>
    <xs:element name="PropertyRef" type="edm:TPropertyRef" minOccurs="1" maxOccurs="unbounded" />
    <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />          
  </xs:sequence>
  <!-- added to allow attributes on the element-->
  <xs:anyAttribute namespace="##other" processContents="lax" />
</xs:complexType>

This almost did the trick – I went past the NullReferenceException… but only to hit an exception with “Failed for unknown reasons” along with “SqlServer” in the message:

Could not load signature of System.Data.Entity.SqlServer.SqlProviderServices:GetExecutionStrategy due to: Failed for unknown reasons.

Unhandled Exception:
System.TypeInitializationException: An exception was thrown by the type initializer for ExtentPlaceholderCreator ---&gt; System.TypeLoadException: Could not load type 'System.Data.Entity.SqlServer.SqlProviderServices' from assembly 'EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
  at (wrapper managed-to-native) System.MonoType:GetPropertiesByName (System.MonoType,string,System.Reflection.BindingFlags,bool,System.Type)
...

Hello??? Anyone there??? I am using MySQL. Any reason you want to load the SqlServer provider? (Yes, the provider was installed by default when I installed the EF package and then, somewhere on my way (must have been after making the app work on .NET Framework), I removed it manually but there should not be a reason to have this provider in the project (and potentially deployed) since it is not being used in my app). This seems like a bug to me but it might have been fixed since alpha2 (a similar issue like this has already been fixed http://entityframework.codeplex.com/workitem/587). Just in case I filed a bug for this https://entityframework.codeplex.com/workitem/1039. To make EF happy I did add the provider for SqlServer and… TADA the app worked.
Just in case – here is the “app” (not even worth putting on github)


namespace EF6MySqlTest
{
  public class Customer
  {
    public int Id { get; set; }
    public string Name { get; set; }
  }

  public class SimpleContext : DbContext
  {
    public SimpleContext()
      : base ("name=MySqlTest")
    {}
    
    public DbSet<Customer> Customers { get; set; }
  }

  class Program
  {
    static void Main(string[] args)
    {
      using (var ctx = new SimpleContext())
      {
        ctx.Customers.Add(new Customer() { Name = "moozzyk" });
        ctx.SaveChanges();
      }

      using (var ctx = new SimpleContext())
      {
        foreach (var c in ctx.Customers)
        {
           Console.WriteLine(c.Name);
        }
      }
    }
  }
}

and the config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <entityFramework>
    <providers>
      <provider invariantName="Devart.Data.MySql" type="Devart.Data.MySql.Entity.MySqlEntityProviderServices, Devart.Data.MySql.Entity, Version=7.6.217.6, Culture=neutral, PublicKeyToken=09af7300eec23701">
        <migrationSqlGenerator type="Devart.Data.MySql.Entity.Migrations.MySqlEntityMigrationSqlGenerator, Devart.Data.MySql.Entity, Version=7.6.217.6, Culture=neutral, PublicKeyToken=09af7300eec23701" />
      </provider>
    </providers>
  </entityFramework>
  
  <system.data>
    <DbProviderFactories>
      <remove invariant="Devart.Data.MySql" />
      <add name="dotConnect for MySQL" invariant="Devart.Data.MySql" 
           description="Devart dotConnect for MySQL" 
           type="Devart.Data.MySql.MySqlProviderFactory, Devart.Data.MySql, Version=7.6.217.0, Culture=neutral, PublicKeyToken=09af7300eec23701" />
    </DbProviderFactories>
  </system.data>
  
  <connectionStrings>
    <add name="MySqlTest" connectionString="server=localhost;user id=moozzyk;password=XXXXXXXXXXXXX;database=TestDb;persist security info=True" providerName="Devart.Data.MySql" />
  </connectionStrings>
</configuration>

To sum up – it was a pretty bumpy road but I am glad I took it. I found a few real issues we should be able to fix before we ship the final version of EF6 and therefore the experience of using EF6 and Mono should be much smoother.

Entity Framework 6 and Model/Database First Work Flows

Visual Studio 2012 (out-of-band release) and Visual Studio 2013 (in-box) now support Model/Database workflows for EF6. See this post for more details.

Entity Framework 6 Alpha 2 has shipped. It has some new cool features (like custom conventions or automatic discovery of entity configurations) and a few other improvements (like improved queries for Linq Enumerable.Contains or changing the default isolation level when creating a SqlServer new database with CodeFirst). Most of the new features and many improvements are CodeFirst related or CodeFirst only. Still there are people who would prefer using a designer to draw a model and create the database or create a model from an existing database and tweak it. The latest version of the Entity Framework Designer which shipped in VS2012 supports only EF5 so it does not seem like it could handle EF6. However after seeing a question on the Entity Framework team blog a couple days ago I thought it would be interesting to really see if this is the case and what it would take to be able to actually use ModelFirst and DatabaseFirst work flows with EF6. In general I thought it might be possible – artifacts have not changed since EF5. As well as most APIs. The two fundamental changes to EF6 are changes to the provider model and all the “new” types that previously lived in System.Data.Entity.dll. New provider model should not be a big concern here – we care about the results here and not about how they are achieved. So, as long as the designer is able to create the database correctly (model first approach) or the edmx file from the database (database first approach) EF6 runtime should be able to use those. Changes to types seemed more worrisome – not only types themselves changed and have new identities but in many cases namespaces changed as well. Luckily the designer now uses T4 templates to generate the code from the edmx file so it is just a pure textual transformation. I expected that I would need to change the T4 templates a bit to make the code compile with EF6 but it should be easy. After all this mental work-out I decided to try it out. I opened VS 2012, created a new project, added a new ADO.NET Entity Framework model, removed references to System.Data.Entity.dll and EntityFramework.dll (5.0.0.0) and added a reference to the EF6 Alpha2 package using NuGet. Then I created a model from an existing database. The project compiled without errors. I added a few lines of code to bring some entities from the database and everything worked. Adding new entities worked as well. Finally I deleted my model and created a new model to try the Model First approach. Similarly I had to remove references to System.Data.Entity.dll and EntityFramework.dll (5.0.0.0) but other than that everything just worked. While what I did was not a very comprehensive test and using VS2012 for EF6 projects is in general not supported I am pretty confident it will work and should be sufficient until a version of the designer that supports EF6 ships.
(Yes, I am a bit disappointed with how easy it was. I hoped this would be a report from a battlefield where I was able to achieve my goal by using a hack here or adding a few lines of code there and maybe even producing a VSIX as a side effect. On the other hand I am happy that even though the post is a little boring the experience for users is much nicer. This is more important).

MSBuild Zip task without external dependencies

I have seen quite a few build systems in my life. Most of them were very complicated with a ton of crap a lot of tools, dependencies, perl scripts, batch files, nested targets files and God knows what else. Figuring out how something worked (or, more often, why something did not work) was time consuming and very frustrating. One of the reasons for this was people were adding some stuff to the build system but no one has ever removed anything. What was even more annoying was that new dependencies oftentimes added tens of new files just to enable one small thing. Not only the enlistments were huge (how about ~200GB without QA tests?) but also configuring the machine to be able to build all this and run the tests was a sort of black magic. Because of all this I always felt bad about the fact that MSBuild did not have a Zip task available out-of-the-box. I feel that not having this one thing is the first step to having a build system that everyone hates. Yes, I know there wasn’t a Zip library in .NET Framework until now. Yes, I know there are third party Zip libraries out there. Yes, I know about MSBuild Community Tasks. Yes, I know MSBuild can somehow zip files internally as it can create VSIX files which are zip files… oops – this probably was not the best example. Anyways, not having a built-in Zip tasks means that you need to add some dependencies to your build system to be able to build your project. This will lead to a build system that no one wants to touch to not break anything. What about sharing just a single project? Like for instance my Code First view gen templates? Is it OK to tell people – “you can build it on your own – here is the project, but first you need to install this and this and this or it won’t build”? I don’t think it’s OK, but before I could not help much. Fortunately, a Zip library was finally added to .NET Framework 4.5. This allowed me creating my own Zip task. How is this task different from, for instance, the Zip task from the MSBuild community tasks? I created it as an inline task. As a resull it is just a small text file I can import to my projects. It can be checked in to my source control. It does not require any additional components being installed or present on the machine apart from what’s already there. If I need to know what the task is doing I can see the source without Reflector. I can easily change the task without having to recompile half of my build system just to be able to build what I actually want to build. (See the Disclaimer at the bottom of the page). The task looks just like this:

<UsingTask TaskName="Zip" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <InputFileNames ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
      <OutputFileName ParameterType="System.String" Required="true" />
      <OverwriteExistingFile ParameterType="System.Boolean" Required="false" />
	</ParameterGroup>
    <Task>
      <Reference Include="System.IO.Compression" />
      <Using Namespace="System.IO.Compression" />
      <Code Type="Fragment" Language="cs">
      <![CDATA[        
        const int BufferSize = 64 * 1024;

        var buffer = new byte[BufferSize];
        var fileMode = OverwriteExistingFile ? FileMode.Create : FileMode.CreateNew;

        using (var outputFileStream = new FileStream(OutputFileName, fileMode))
        {
          using (var archive = new ZipArchive(outputFileStream, ZipArchiveMode.Create))
          {
            foreach (var inputFileName in InputFileNames.Select(f => f.ItemSpec))
            {
              var archiveEntry = archive.CreateEntry(Path.GetFileName(inputFileName));

              using (var fs = new FileStream(inputFileName, FileMode.Open))
              {
                using (var zipStream = archiveEntry.Open())
                {
                  int bytesRead = -1;
                  while ((bytesRead = fs.Read(buffer, 0, BufferSize)) > 0)
                  {
                    zipStream.Write(buffer, 0, bytesRead);
                  }
                }
              }
            }
          }
        }        
      ]]>
      </Code>
    </Task>
  </UsingTask>

Using the task is simple. Put the task to a separate file and import the file to the csproj file. In fact the file is available in my github repo – https://github.com/moozzyk/MSBuild-Tasks. Once you import the file to the project you just invoke the task as you would invoke any other task – for example (this is an actual except from one of my csproj files):


  <Import Project="common.tasks" />
  
  <Target Name="BeforeBuild">
    <ItemGroup>
      <FilesToZip Include="$(ProjectDir)\PayloadUnzipped\*.*" />
    </ItemGroup>
    <Zip 
      InputFileNames="@(FilesToZip)"
      OutputFileName="$(ProjectDir)$(TargetZipFile)"
      OverwriteExistingFile="true" />
  </Target>

That’s pretty much it. Works for me and hopefull will work for you.

Disclaimer:
I am not trying to diminish MSBuild Community Tasks or claim that inline tasks will solve all problems of this world. I am trying to say that for small simple tasks inline tasks can be just much more convenient.