IdentityServer / IdentityServer3.EntityFramework

EntityFramework persistence layer for IdentityServer3
Apache License 2.0
68 stars 97 forks source link

AutoMapper 4.1.0 breaks .ToEntity() #72

Closed MAOliver closed 8 years ago

MAOliver commented 9 years ago

Trying to run a code first migration after upgrading to AutoMapper 4.1.0 results in the following stacktrace (I'm seeding my database):

PM> Update-Database -ConfigurationTypeName Auth.Api.Migrations.ClientConfiguration.Configuration -ConnectionStringName IdSvr3Config -StartUpProjectName Auth.Api
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending explicit migrations.
Running Seed method.
System.TypeInitializationException: The type initializer for 'IdentityServer3.Core.Models.EntitiesMap' threw an exception. ---> System.TypeLoadException: Could not load type 'AutoMapper.ISourceMemberConfigurationExpression`1' from assembly 'AutoMapper, Version=4.1.0.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005'.
   at IdentityServer3.Core.Models.EntitiesMap..cctor()
   --- End of inner exception stack trace ---
   at IdentityServer3.Core.Models.EntitiesMap.ToEntity(Client s)
   at Auth.Api.Migrations.ClientConfiguration.Configuration.Seed(ClientConfigurationDbContext context) in D:\wrk\fnftfs\RateServices\Auth\Main\source\apis\Auth.Api\Migrations\ClientConfiguration\Configuration.cs:line 130
   at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
The type initializer for 'IdentityServer3.Core.Models.EntitiesMap' threw an exception.

Rolling back to 4.0.4 restores the lost functionality.

brockallen commented 9 years ago

Ask @jbogard :)

Just kidding -- I can look into it when I get a chance.

skivsoft commented 9 years ago

It seems like this is related to AutoMapper#945.

brockallen commented 9 years ago

Ok, thanks for looking into it some more.

jbogard commented 9 years ago

I fixed the issue in 4.1.1, it looks like the tests pass locally. @MAOliver can you try again?

brockallen commented 9 years ago

Thx @jbogard

MAOliver commented 9 years ago

@brockallen @skivsoft thanks for the quick attention. Sorry for taking so long to get back to re-testing. @jbogard Sorry, still getting an exception, see below:

PM> Update-Database -ConfigurationTypeName Auth.Api.Migrations.ClientConfiguration.Configuration -ConnectionStringName IdSvr3Config
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending explicit migrations.
Running Seed method.
System.TypeInitializationException: The type initializer for 'IdentityServer3.Core.Models.EntitiesMap' threw an exception. ---> System.TypeLoadException: Could not load type 'AutoMapper.ISourceMemberConfigurationExpression`1' from assembly 'AutoMapper, Version=4.1.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005'.
   at IdentityServer3.Core.Models.EntitiesMap..cctor()
   --- End of inner exception stack trace ---
   at IdentityServer3.Core.Models.EntitiesMap.ToEntity(Client s)
   at Auth.Api.Migrations.ClientConfiguration.Configuration.Seed(ClientConfigurationDbContext context) in D:\wrk\fnftfs\RateServices\Auth\Main\source\apis\Auth.Api\Migrations\ClientConfiguration\Configuration.cs:line 26
   at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
The type initializer for 'IdentityServer3.Core.Models.EntitiesMap' threw an exception.

My seed code looks like this:

internal sealed class Configuration : DbMigrationsConfiguration<IdentityServer3.EntityFramework.ClientConfigurationDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            MigrationsDirectory = @"Migrations\ClientConfiguration";
        }

        protected override void Seed(IdentityServer3.EntityFramework.ClientConfigurationDbContext context)
        {
            var clients = GetInfrastructure()
                .Union(GetIntegrators())
                .Union(GetDemoClients());

            foreach (var client in clients)
            {
                context.Clients.AddOrUpdate(cl => cl.ClientId, client.ToEntity()); //this is my line 26
            }
        }

/// truncated

}

I can create a demo project + powershell script if needed

jbogard commented 9 years ago

@MAOliver Yeah, all the tests pass now for me, so not sure what is different on your version.

brockallen commented 9 years ago

@MAOliver it's entirely possible it's something how we're using it, so if you have time to debug further I'd appreciate it.

MAOliver commented 9 years ago

@jbogard @brockallen Yeah, I'll pull the projects down tonight and see if I can set up a small case to replicate the problem for all parties involved.

MAOliver commented 9 years ago

@jbogard @brockallen https://github.com/MAOliver/recreate-issue-72 created this to replicate the issue.

And @brockallen you're right, I pulled the IdentityServer.EntityFramework project and added my test to that project and it ran without issue. This suggests that the issue is in how the project is being packaged for nuget.

Maybe there was a change in the dependencies for Automapper for 4.1 ?

MAOliver commented 9 years ago

Kinda scratching my head at this point. The same code that fails inside the EntitiesMap in IdentityServer3.EntityFramework succeeds inside the unit test project.

Maybe it's something about the binding redirect that isn't working correctly between the two different versions 4.0.4 and 4.1.0?

MAOliver commented 9 years ago

@jbogard @brockallen Alright. So, mystery solved. A marker interface was removed between AutoMapper 4.0.4 -> AutoMapper 4.1.0+. The compiled code depends on the interface and the new version doesn't have it. The assembly redirect fails and you get a typeloadexception

(4.0.4):

https://github.com/AutoMapper/AutoMapper/blob/88be8a1feda45f5abecee875ff3c85d719bdb955/src/AutoMapper/ISourceMemberConfigurationExpression.cs

(master / 4.1.0+) https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/ISourceMemberConfigurationExpression.cs

The removed interface:

    /// <summary>
    /// Source member configuration options
    /// </summary>
    /// <typeparam name="TSource">Source type</typeparam>
    public interface ISourceMemberConfigurationExpression<TSource> :  ISourceMemberConfigurationExpression
    {
    }
jbogard commented 9 years ago

Ahhhh nuts. I could put it back in, I thought I might add members to it but never did.

Sent from my iPhone

On Nov 4, 2015, at 3:37 AM, Matthew Oliver notifications@github.com wrote:

@jbogard @brockallen Alright. So, mystery solved. A marker interface was removed between AutoMapper 4.0.4 -> AutoMapper 4.1.0+. The compiled code depends on the interface and the new version doesn't have it. The assembly redirect fails and you get a typeloadexception

(4.0.4):

https://github.com/AutoMapper/AutoMapper/blob/88be8a1feda45f5abecee875ff3c85d719bdb955/src/AutoMapper/ISourceMemberConfigurationExpression.cs

(master / 4.1.0+) https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/ISourceMemberConfigurationExpression.cs

The removed interface:

/// <summary>
/// Source member configuration options
/// </summary>
/// <typeparam name="TSource">Source type</typeparam>
public interface ISourceMemberConfigurationExpression<TSource> :  ISourceMemberConfigurationExpression
{
}

— Reply to this email directly or view it on GitHub.

MAOliver commented 9 years ago

@jbogard Most of the users of your API don't know that interface exists due to type inference in .Net. That said, I'd probably put it back because the burden on your users is greater if you remove it.

edandersen commented 8 years ago

+1 just been hit by this. Downgrading Automapper to 4.0.4 and changing the assembly redirect fixed it.

brockallen commented 8 years ago

So I'm about to do an update on this library -- is the recommendation to update the AutoMapper version referenced?

MAOliver commented 8 years ago

Yes. That'd be the easiest way to address this from this side.

brockallen commented 8 years ago

Okies, I'll do this update in the next couple of days to line up with our 2.2 release.

brockallen commented 8 years ago

Ok, I updated the version of automapper on the dev branch.

martinlevington commented 8 years ago

I have upgrade to automapper 4.2.0 and think that the issue has come back

AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.

Mapping types: Client -> Client IdentityServer3.EntityFramework.Entities.Client -> IdentityServer3.Core.Models.Client

Destination path: Client

Source value: System.Data.Entity.DynamicProxies.Client_963A28B8041D113E74422A64B1B1E6D0EC7FD793894BA39850CE92FB2730CD73 at AutoMapper.MappingEngine.Map(ResolutionContext context) at AutoMapper.Mapper.MapCore(Object source, Type sourceType, Type destinationType, MappingOperationOptions options) at AutoMapper.Mapper.AutoMapper.IMapper.Map(Object source, Type sourceType, Type destinationType, Action1 opts) at AutoMapper.Mapper.AutoMapper.IMapper.Map[TSource,TDestination](TSource source) at AutoMapper.Mapper.Map[TSource,TDestination](TSource source) at IdentityServer3.EntityFramework.Entities.EntitiesMap.ToModel(Client s) in c:\local\identity\server3\EntityFramework\Source\Core.EntityFramework\Extensions\EntitiesMap.cs:line 57 at IdentityServer3.EntityFramework.ClientStore.<FindClientByIdAsync>d__2.MoveNext() in c:\local\identity\server3\EntityFramework\Source\Core.EntityFramework\Stores\ClientStore.cs:line 50 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()

brockallen commented 8 years ago

Yep, we just noticed this in the past couple of days -- I'm on it...