npgsql / npgsql

Npgsql is the .NET data provider for PostgreSQL.
http://www.npgsql.org
PostgreSQL License
3.25k stars 825 forks source link

Npgsql 4.0.0-preview2 with EntityFramework automigrtation #1888

Closed naigsa closed 6 years ago

naigsa commented 6 years ago

Before submitting

After upgarde npgsql from 3.2.7 to 4.0.0-preview2 automigrations in entity framework are not working.

Steps to reproduce

Create two ef contexts with one migration table and with settings:

AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;

The issue

i get error "column "ContextKey" of relation "__MigrationHistory" already exists"

"ClassName": "Npgsql.PostgresException",
        "Message": "External component has thrown an exception.",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Npgsql.NpgsqlConnector.<ReadMessageLong>d__162.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Npgsql.NpgsqlConnector.<ReadMessageLong>d__162.MoveNext() in C:\\projects\\npgsql\\src\\Npgsql\\NpgsqlConnector.cs:line 1035\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()\r\n   at Npgsql.NpgsqlDataReader.<NextResult>d__45.MoveNext() in C:\\projects\\npgsql\\src\\Npgsql\\NpgsqlDataReader.cs:line 460\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Npgsql.NpgsqlDataReader.NextResult() in C:\\projects\\npgsql\\src\\Npgsql\\NpgsqlDataReader.cs:line 333\r\n   at Npgsql.NpgsqlCommand.<ExecuteDbDataReader>d__101.MoveNext() in C:\\projects\\npgsql\\src\\Npgsql\\NpgsqlCommand.cs:line 1233\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()\r\n   at Npgsql.NpgsqlCommand.<ExecuteNonQuery>d__93.MoveNext() in C:\\projects\\npgsql\\src\\Npgsql\\NpgsqlCommand.cs:line 1044\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Npgsql.NpgsqlCommand.ExecuteNonQuery() in C:\\projects\\npgsql\\src\\Npgsql\\NpgsqlCommand.cs:line 1027\r\n   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)\r\n   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(MigrationStatement migrationStatement, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinTransaction(IEnumerable`1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinNewTransaction(IEnumerable`1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection)\r\n   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements, DbTransaction existingTransaction)\r\n   at System.Data.Entity.Migrations.DbMigrator.UpgradeHistory(IEnumerable`1 upgradeOperations)\r\n   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)\r\n   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)\r\n   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)\r\n   at System.Data.Entity.MigrateDatabaseToLatestVersion`2.InitializeDatabase(TContext context)\r\n   at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)\r\n   at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()\r\n   at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)\r\n   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)\r\n   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)\r\n   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()\r\n   at System.Data.Entity.Internal.Linq.InternalSet`1.AsNoTracking()\r\n   at System.Data.Entity.Infrastructure.DbQuery`1.AsNoTracking()\r\n   at Beeline.Cms.Dal.Repositories.BaseCacheEfRepository`1.<GetCachedEntites>b__10_0() in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Dal\\Repositories\\BaseCacheEfRepository.cs:line 64\r\n   at Beeline.Cms.Domain.Services.MemoryCacheService.GetOrAdd[T](String key, Func`1 getData, Int32 expiry) in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Domain\\Services\\MemoryCacheService.cs:line 36\r\n   at Beeline.Cms.Dal.Repositories.BaseCacheEfRepository`1.GetCachedEntites() in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Dal\\Repositories\\BaseCacheEfRepository.cs:line 63\r\n   at Beeline.Cms.Dal.Repositories.EntityRepository.GetByFilter(EntityFilter filter) in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Dal\\Repositories\\EntityRepository.cs:line 32\r\n   at Beeline.Cms.Domain.Services.EntityService.GetEntityByFilter(EntityFilter filter) in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Domain\\Services\\EntityService.cs:line 71\r\n   at Beeline.Cms.Domain.Services.EntityService.GetEntityByAlias(String alias) in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Domain\\Services\\EntityService.cs:line 128\r\n   at Beeline.Cms.Api.Controllers.EntityController.<SaveEntity>d__5.MoveNext() in C:\\Users\\ISNaumov\\agent\\_work\\7\\s\\Beeline.Cms.Api\\Controllers\\EntityController.cs:line 87\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__1`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nMoveNext\nNpgsql, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7\nNpgsql.NpgsqlConnector+<ReadMessageLong>d__162\nVoid MoveNext()",
        "HResult": -2147467259,
        "Source": "Npgsql",
        "WatsonBuckets": null,
        "Severity": "ОШИБКА",
        "SqlState": "42701",
        "MessageText": "столбец \"ContextKey\" отношения \"__MigrationHistory\" уже существует",
        "Detail": null,
        "Hint": null,
        "Position": 0,
        "InternalPosition": 0,
        "InternalQuery": null,
        "Where": null,
        "SchemaName": null,
        "TableName": null,
        "ColumnName": null,
        "DataTypeName": null,
        "ConstraintName": null,
        "File": "tablecmds.c",
        "Line": "5096",
        "Routine": "check_for_column_name_collision"

Further technical details

Net Framework: 4.6.1 EntityFramework: 6.2.0 Npgsql version: 4.0.0-preview2 PostgreSQL version: 9.6.1 Operating system: windows 7

roji commented 6 years ago

This is a PostgreSQL error informing you that a column already exists, I can't really think of anything at the Npgsql ADO.NET layer that could trigger this (between 3.2.7 and 4.0.0)... All Npgsql does is send the SQL to PostgreSQL and read back the results.

Can you double-check this isn't an unrelated issue on your end somehow? If not, a wireshark comparison of the traffic between Npgsql and PostgreSQL would help investigate this - if there really is some significant change between 3.2.7 and 4.0.0 it'll show up.

naigsa commented 6 years ago

ok, i will investigate it and will write about issue. But, i sure that is influence of npgsql 4, because I did the actions below: upgrade npgsql 4 - i got above error, downgrade package back - all works fine

naigsa commented 6 years ago

i am created minimal project for show this issue https://nofile.io/f/YbafgxkZb5T/NpgsqlTest1.zip Solution has two porjects. One with npgsql3 and one with npgsql4. Both projects has identical logic. For start project create empty db and add uuid support:

SQl Command: CREATE EXTENSION IF NOT EXISTS "uuid-ossp"

Then invoke post method:

POST /entity HTTP/1.1 Host: localhost:62524 Content-Type: application/json Cache-Control: no-cache Postman-Token: 33e0ff06-c275-4205-8a44-8f6747622f8a

{ "alias": "test", "name": "test" }

roji commented 6 years ago

Can you please post the PostgreSQL statement logs for both runs, i.e. once with Npgsql 3.2 (successful) and once with the newly-released Npgsql 4.0 (failure)?

naigsa commented 6 years ago

I checked the problem with version 4.0.0 and automigrations works fine.

roji commented 6 years ago

Great, thanks for confirming.