Efcore: EF Core tooling for .NET UWP

Created on 1 Sep 2017  路  38Comments  路  Source: dotnet/efcore

Currently, EF Core tooling attempts to use .NET Framework to run user code on UWP applications. In the past, we encountered problems with that approach whenever types that were not the same between UWP and .NET Framework. One example of that was DataAnnotations. We addressed those with binding redirects and intercepting assembly resolution.

While testing EF Core 2.0 with .NET UWP 6.0 we found that there are new types that present similar problems. E.g.:

System.TypeLoadException: Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
System.TypeLoadException: Could not load type 'System.MarshalByRefObject' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

There different ways we can address, in order from short, middle and long term:

  1. Update our guidance for UWP to place the EF Core model in a separate project that is compatible with our tooling
  2. Update our tooling to show a nice error pointing to the guidance described above
  3. Use more binding redirect and assembly resolution tricks to make more types work (talked to @bricelam, he thinks this is feasible)
  4. Switch to run the user code in .NET Core, which is a closer match to UWP and is apparently the approach the XAML designer is now using (see this post)
closed-duplicate punted-for-2.1

Most helpful comment

If I change EFCore version to v1.1.0 and same with Tools I get this instead....

System.IO.FileNotFoundException: Could not load file or assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.
File name: 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
at Microsoft.EntityFrameworkCore.Design.Internal.StartupInvoker.<>c.<.ctor>b__6_0(TypeInfo t)
at System.Linq.Enumerable.WhereArrayIterator1.MoveNext() at System.Linq.Enumerable.<ConcatIterator>d__591.MoveNext()
at System.Linq.Enumerable.d__591.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.FirstOrDefaultTSource

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

Could not load file or assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.

All 38 comments

As min, try to make the failure experience (directing to class library) better in 2.0.1.

Hmm... Everything is working for me on 2.0.0 with the latest pre-releases:

Windows: 16281 (rs3_release)
Windows SDK: 16278
Visual Studio: 26906 (d15rel)
Microsoft.NETCore.UniversalWindowsPlatform: 6.0.0-preiew1-25631-01

@AndriySvyryd Any additional details on how to repro? I just:

  1. Created a new UWP app targeting the latest SDK
  2. Installed EFCore.Sqlite and Tools
  3. Added a DbContext
  4. Add-Migraiton Test

The other exception is from calling Scaffold-DbContext

That repros.

CultureInfo is coming from a System.Collections.Immutable reference.
MarshalByRefObject is coming from System.Data.SqlClient.

Not a good sign since we can't control those references...

@divega I don't think option 3 is feasible anymore.

Interesting. Can't we control where System.Data.SqlClient is coming from?

Ok, after talking to @bricelam I understand that the version of System.Data.SqlClient is not there anymore when we try to load, because only the version that the UWP application is going to use is available.

@bricelam new fwlink for UWP tooling guidance is https://go.microsoft.com/fwlink/?linkid=858496. Right now it points to the UWP tutorial, which needs updating, but we can point it to a new page.

Created #9827 to track the 2.0.1 part of this issue. Moving the remainder to 2.1.

Fix #9423 as part of this work.

Hmm... With .NET Framework 4.7.1 we might be able to go back to the original approach. It looks they're adding runtime facades for .NET Standard 2.0.

We will investigate this again after the UWP release and see if there is anything cheap we can do then.

I've got a UWP app targeting UWP 6.0.1. I've moved my domain classes and data layer (db context) classes into .NET Standard 2.0 class libraries. My UWP application is referencing a UWP repository project which is referencing my data layer. When I try to add a migration, I'm still getting the below error. Wasn't moving my data layer to .NET Standard supposed to resolve this?

System.TypeLoadException: Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
at System.Collections.Immutable.ImmutableSortedDictionary2.Node.SetOrAdd(TKey key, TValue value, IComparer1 keyComparer, IEqualityComparer1 valueComparer, Boolean overwriteExistingValue, Boolean& replacedExistingValue, Boolean& mutated) at System.Collections.Immutable.ImmutableSortedDictionary2.Node.SetItem(TKey key, TValue value, IComparer1 keyComparer, IEqualityComparer1 valueComparer, Boolean& replacedExistingValue, Boolean& mutated)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.RelationshipDiscoveryConvention.GetNavigationCandidates(EntityType entityType)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.RelationshipDiscoveryConvention.FindRelationshipCandidates(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.RelationshipDiscoveryConvention.DiscoverRelationships(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnEntityTypeAdded(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.AddEntityType(EntityType entityType)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity type, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(Type type)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.FindSets(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.FindSets(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredServiceT
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetServiceTService
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

@bgulrich are you invoking the command on your data layer project? (e.g. via -Project MyApp.Data)

@bricelam Yes, I was setting the default project to my data layer project in the package manager console. I tried the command parameter as well to no avail.

Have this issue too, it was working on this computer until I pulled the git repo I have on another computer and made a push.... then back to the original computer to make a pull and....

This goes for all migration actions I've tried

System.TypeLoadException: Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
at System.Collections.Immutable.ImmutableSortedDictionary2.Node.SetOrAdd(TKey key, TValue value, IComparer1 keyComparer, IEqualityComparer1 valueComparer, Boolean overwriteExistingValue, Boolean& replacedExistingValue, Boolean& mutated) at System.Collections.Immutable.ImmutableSortedDictionary2.Node.SetItem(TKey key, TValue value, IComparer1 keyComparer, IEqualityComparer1 valueComparer, Boolean& replacedExistingValue, Boolean& mutated)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.RelationshipDiscoveryConvention.GetNavigationCandidates(EntityType entityType)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.RelationshipDiscoveryConvention.FindRelationshipCandidates(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.RelationshipDiscoveryConvention.DiscoverRelationships(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnEntityTypeAdded(InternalEntityTypeBuilder entityTypeBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.AddEntityType(EntityType entityType)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity type, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(Type type)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.FindSets(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.FindSets(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredServiceT
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetServiceTService
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.RemoveMigration(String contextType, Boolean force)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.RemoveMigrationImpl(String contextType, Boolean force)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

If I change EFCore version to v1.1.0 and same with Tools I get this instead....

System.IO.FileNotFoundException: Could not load file or assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.
File name: 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
at Microsoft.EntityFrameworkCore.Design.Internal.StartupInvoker.<>c.<.ctor>b__6_0(TypeInfo t)
at System.Linq.Enumerable.WhereArrayIterator1.MoveNext() at System.Linq.Enumerable.<ConcatIterator>d__591.MoveNext()
at System.Linq.Enumerable.d__591.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.FirstOrDefaultTSource

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

Could not load file or assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.

I have the same issue when running add-migration on top of EntityFrameworkCore.Sqlite 2.0.0 and UWP 6.0.1 as @bgulrich and @ChristianJonsson :
System.TypeLoadException: Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

I've tried separating the model and context in separate NetStandard 2.0 class library and referencing that from UWP 6.0.1 app but getting the same error.

Do you have any example on code that works with Sqlite 2.0.0 and UWP 6.0.1. (workarounds included)?

Very interested in what @mtosic is asking as well, in regards to workaround/example code.

My workaround at the moment was to move my DB to Realms instead.... which is not what I wanted at all, but cannot get SQLite to work atm with UWP.

For my Xamarin Android and iOS projects SQLite still works....

@ChristianJonsson My EF Core v1 migrations work fine with Core 2, so you might just try downgrading your packages, building the migrations, then upgrading again.

@bgulrich do you have an example of that? When I downgrade EF tools and EF.SQLite in UWP 6.0.1, app won't build so I can't even run migrations.

@mtosic I don't have an example. I just used the migrations I had already created when using an older version of EF in UWP project targeting Windows 10 Creator's Update. When I built the migration, I was targeting an older version of UWP in my project. You might try rolling back to 5.x. Here's that section of my old csproj:


5.4.0

I have the same issue when running add-migration on top of EntityFrameworkCore.Sqlite 2.0.0 and UWP 6.0.1 as @bgulrich and @ChristianJonsson and @mtosic :

System.TypeLoadException: Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

I created a new .Net Standard 2.0 class library as the only project in the solution and got the same error when running Add-Migration. That class library does not reference 'System.Globalization.CultureInfo' at all.

I then created a .Net Core 2.0 class library and Add-Migration ran without error. Unfortunately UWP cannot reference a .Net Core 2.0 class library, only ,Net Standard 2.0.

To make the class library work with both UWP and EF Tools it needs to target both .NET Standard 2.0 and .NET Core 2.0 (or .NET Framework 4.6.1):

<TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>

However this requires EF 2.0.1, so please wait until it's released if you are getting errors.

@AndriySvyryd any ETA on EF 2.0.1?

It's not 2.0.1, but the nightly dev feed includes all of its fixes and more if anyone is eager to try them out.

Oh look: there's a nightly feed of the patch available now.

@bricelam either i'm doing something wrong or this nightly feed patch has not fixed this problem. I followed the above mentioned announcement but still getting the error:-

System.TypeLoadException: Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

below is a picture that describe better than words.

error

@Eilon @natemcmaster It looks like Microsoft.EntityFrameworkCore.Tools.DotNet depends on Microsoft.NETCore.App. Do we need to remove this?

I'm not aware of any reasons to remove it. DotNetCliToolReference packages are installed in context independent from the users's app. That means you don't need to add netcoreapp2.0 to install a DotNetCliToolReference.

That said, since the pre-release version of this package depends on a version of Microsoft.NETCore.App that isn't on NuGet.org yet and we didn't mirror it into our patch feed, users must add this feed as well

https://dotnet.myget.org/F/dotnet-core/api/v3/index.json

cref https://github.com/aspnet/Home/issues/2254#issuecomment-339141100

@bricelam Some feedback on the issue:-

  1. After adding the feed that @natemcmaster provided, i was able to use the following target frameworks without getting the error about Microsoft.NETCore.App:-
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>
<NoWarn>$(NOWARN);NU1605</NoWarn>
</PropertyGroup>
  1. Then after restoring every package i needed and referencing every package with version 2.0.1-rtm-203 i need, i was still NOT able to use the Add-Migration command inside the Nuget Package Manager. As it gives the following error:-

PM> Add-Migration HomeAutomationDB
Startup project 'HomeAutomation.UWP' is a Universal Windows Platform app. This version of the Entity Framework Core Package Manager Console Tools doesn't support this type of project. For more information on using the EF Core Tools with UWP projects, see https://go.microsoft.com/fwlink/?linkid=858496

  1. Despite the second point i was ABLE to do a migration using CMD:-

dotnet ef migrations add HomeAutomationDB

Hope this will helps you (If it is some kind of bug that needs to be fixed)

This was happening to me trying to upgrade a 1.1 UWP app with Sqlite to 2.0.

Could not load type 'System.Globalization.CultureInfo' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

I moved EF parts into a .NET Standard class library and thought it helped, but once the classes were fleshed out the error returned.

I did not switch to the dev feed, this is with 2.0 bits still. The tooling can generate a simple class with minimal data annotations. I experimented until the problem was identified, which in my case was relationships. If I dropped the "details" from the "master" (remove List <Details> property from the Master class) and also remove the "master" property from the "detail" class then the tooling works and the migration is added. In my case this is an acceptable workaround. Huzzah. Thanks!

Apparently aspnetcore 2.0.1 official release is out and I'm still having the "Could not load type 'System.Globalization.CultureInfo'" issue. Did this get fixed for anyone without the dev feed?

Any updates? I can't get it to work with the data layer inside a separate class library project and the latest 2.1.0-preview1-final Version of EntityFrameworkCore.
If I try to cross-target the class library to <TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks> I can't add it as a reference to my UWP project.

@Ullmie02 Cross-targeting is a bit broken with UWP. Instead, create a dummy .NET Core console application to use as your startup project. The dummy project will reference your data layer.

Closing this in favor of tracking via duplicate #7152 for Xamarin, which has the same underlying issues.

Was this page helpful?
0 / 5 - 0 ratings