dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.82k stars 3.2k forks source link

PMC Tools: Cannot load type IOperationResultHandler #8064

Closed mheilimo closed 2 years ago

mheilimo commented 7 years ago

I made migration first time to my average size project (about 100 tables) and now I am trying to do changes to the azure sql db with 'Update-Database' call in package manager console.

I will get this error always: Exception message: Stack trace:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.Remoting.RemotingException: Cannot load type 'Microsoft.EntityFrameworkCore.Design.IOperationResultHandler, Microsoft.EntityFrameworkCore.Design, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.

Server stack trace: at System.Runtime.Remoting.Messaging.MethodCall.ResolveMethod(Boolean bThrowIfNotResolved) at System.Runtime.Remoting.Messaging.MethodCall..ctor(SmuggledMethodCallMessage smuggledMsg, ArrayList deserializedArgs) at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[] reqStmBuff, SmuggledMethodCallMessage smuggledMcm, SmuggledMethodReturnMessage& smuggledMrm) at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object[] args)

Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at Microsoft.EntityFrameworkCore.Design.IOperationResultHandler.OnError(String type, String message, String stackTrace) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.Activator.CreateInstance(String assemblyString, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark) at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.AppDomain.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.AppDomain.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at Microsoft.EntityFrameworkCore.Tools.AppDomainOperationExecutor.Execute(String operationName, Object resultHandler, IDictionary arguments) at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid4[T0,T1,T2,T3](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) at Microsoft.EntityFrameworkCore.Tools.OperationExecutorBase.InvokeOperationImpl(String operationName, IDictionary arguments) at Microsoft.EntityFrameworkCore.Tools.OperationExecutorBase.UpdateDatabase(String migration, String contextType) at Microsoft.EntityFrameworkCore.Tools.Commands.DatabaseUpdateCommand.Execute() at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args) at Microsoft.EntityFrameworkCore.Tools.Program.Main(String[] args) Exception has been thrown by the target of an invocation.

I understood that it try to remove this table primary key - there is multiple similar calls before that: migrationBuilder.DropPrimaryKey(name: "pk_usr", table: "usr");

What might be my reasons to my problem - thanks for your help!

Steps to reproduce

You can't reproduce this maybe because I can't paste full db here, but you might know what might be reason anyway.

References what I have there are (all are 1.1.1.0): Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.Relational Microsoft.EntityFrameworkCore.Relational.Design Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.SqlServer.Design

bricelam commented 7 years ago

Are you using version 1.1.0 of Microsoft.EntityFrameworkCore.Tools?

mheilimo commented 7 years ago

Thanks for your answer - I double cheched that I have latest tools too.

bricelam commented 7 years ago

Could you share your project so we can investigate?

mheilimo commented 7 years ago

I will send you source package via mail.

bricelam commented 7 years ago

I hate to say it, but it works for me. Ensure the Default project and StartUp Project are set as expected, and check the output with -Verbose to make sure it's looking where you expect it to.

mheilimo commented 7 years ago

Hi Brice!

Unfortunately I have accidentally given you a non-working project so it can’t have worked ok in your testing.

There were a few mistakes in the model so even the first create db didn't work - one was my bug and the other was created by Scaffold-DbContext call (I fixed these issues today after I started testing it more after your feedback).

So if you open the project and and do just Update-Database it works because it doesn't create db (what I would expect if db is empty), but if you perform the steps below it will fail because new migration is mandatory to do after Scaffold-DbContext call or it will create only an empty db. I think that it is a bug that Scaffold-DbContext doesn't create some 'initial-state' migration to db:

  1. Scaffold-DbContext "XXXXXX" Microsoft.EntityFrameworkCore.SqlServer -OutputDir DataModels -Context EntitiesModel
  2. Add-Migration "InitialMigration"
  3. Update-Database

I am sure that it will fail. It looks like unfortunately Scaffold-DbContext call is so buggy currently that it is not practical. I can't even take the db and do these steps to create empty db without any changes to script. I have to start commenting out a lot of code to make it work and a fundamental problem is also that it doesn't create initial state to db so you can't run my steps 1,2,3 for the same db that you just created from db to model (if you do so it starts create db from scratch - my opinion is that it should create initial migration to db and continue from there)

BTW, I found one bug also in fluent api - it doesn't cut index names if default names are too long - for example this index will create error:

entity.HasIndex(
                          e => new
                                   {
                                       e.UserGUID,
                                       e.UsedPersonalDataGUID,
                                       e.SummaryDateTime,
                                       e.TimezoneOffsetMins,
                                       e.Modified,
                                       e.Name,
                                       e.CalculationStatusBuffalo,
                                       e.Disabled,
                                       e.MeasurerGUID,
                                       e.SubjectGUID
                                   });

CREATE INDEX [index name] is too long. Maximum length is 128.

Please tell me if I misunderstood something and thanks a lot for your help. -Verbose don't give more information.

mheilimo commented 7 years ago

Now I faked this wanted behavior (initial state in db) so that I can continue after Scaffold-DbContext call.

I create one empty db with a script and then I copy my manually added empty db. I will copy this dbo.__EFMigrationsHistory state to wanted db (that was just created from Scaffold-DbContext call) and then it should work because if Scaffold-DbContext works properly there shouldn't be any changes after one Scaffold-DbContext and database-update calls - right?

bricelam commented 7 years ago

Sorry, by work, I meant that I am not encountering the cannot load type IOperationResultHandler error. The other issues are, of course, still present, but EF is working as expected.

For guidance on how to bootstrap an existing database to use migrations, you might find the EF6 documentation about how to use Migrations with an existing database useful. The principles still apply to EF Core.

Scaffold-DbContext doesn't create some 'initial-state' migration

This would be a nice feature to add. I still don't think we'd do it by default though, because not everyone that reverse engineers and existing database schema will want to use Migrations to manage schema changes. Some will simply update the model to reflect the database (see #831). I'll add a note to #2167 about enhancing Scaffold-DbContext.

If Scaffold-DbContext works properly there shouldn't be any changes after one Scaffold-DbContext and database-update calls - right?

Correct, the database used to create a model with Scaffold-DbContext, should be the same as a database created with Migrations using that same model.

Your method of faking the behavior corresponds to the guidance we recommend for accomplishing this scenario.