Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code First: Error seeding data when Table is created in same migration. [DNET1003] #917

Open
firebird-automations opened this issue Jan 11, 2021 · 6 comments

Comments

@firebird-automations
Copy link

Submitted by: Giacomo Policicchio (pgiacomo)

Due to Firebird behavior, in same transaction is not possible to insert data in a newly created Table. So, using Entity.HasData in OnModelCreating in same Migration where the table is created, an error is raised and migration fails.
Scripting the migration instead of applying it with update-database confirms my supects, the structure is:

START TRANSACTION;
DDL statements
HasData DML statements
Insert into 'MigrationsHistoryTable'
COMMIT;

First solution that came to my mind reading the code could be to wrap relevant DDL statemens between "set autoddl on;" and "set audoddl off" statements, e.g. in "Migrations/FbMigrationsSqlGenerator,cs", method "Generate(CreateTableOperation....", it would be easy to add these statements, maybe adding a flag in FbOptionsExtension to preserve default original behavior.
But this solution is too dirty, because if for any reason migration fails, DDL command are executed partially needing to manually recover, if possible, prior database state. So the ideal solution instead would be to inject a "commit" and a "start transaction" between ddl and dml commands, so the only risks will be related to DML failing for any reason, but a fail like that could easily recovered. For this soultion I've to study more EF Core internal processes.
What do you thinK?

Bye

@firebird-automations
Copy link
Author

Commented by: @cincuranet

set autoddl on is not a DDL statement. It's something that ISQL recognizes and handles. So another nail to the coffin. Injecting transaction handling is not a great idea either, because it's not going to work for generated script.

Executing in autonomous transaction is probably the only way to go. It is something I'm handling in EF6 (https://github.com/cincuranet/FirebirdSql.Data.FirebirdClient/blob/master/Provider/src/EntityFramework.Firebird/FbMigrationSqlGenerator.cs#L293), but that also means that the TIL has to be lowered from i.e. Serializable to i.e. Read Committed. And that's not nice and smooth either.

@firebird-automations
Copy link
Author

Commented by: Giacomo Policicchio (pgiacomo)

Yes it would be an unnecessary mess, sorry for your wasted time, and thank you for explanation. I gave also a glance at efcore sources, and I don't see any good solution to overcome FB behavior. It's really better to split data seeding from structure migration.

Thank You

@firebird-automations
Copy link
Author

Commented by: @cincuranet

It's not wasted time. An open discussion about a problem is always good.

The problem is really two pieces. 1) overcoming (or not) Firebird limitations and 2) keeping expected behavior across EF Core providers. Obviously for 1) you can say that we want EF Core to just work and don't bother with "internal" details. But also with 2) the behavior (i.e. doing the changes in two TXs - no matter what way) might be confusing. I don't have clear answer which path is better.

@firebird-automations
Copy link
Author

Commented by: Giacomo Policicchio (pgiacomo)

I think EF core is tailored around MSSQL, so, it is not easy to keep a behavior decently consistent across providers. For doing so, EF should have been designed intersecting features of major providers, so loosing a lot of specific features. At the end, it is on developer shoulder to mantain a consistent behavior of an application if interchangeable provider is required, and perhaps it is better this way..
However, I'm using Pomelo.EntityFrameworkCore.MySql on a project and I don't like what when a migration fails, because all action performed until the exception aren't rolled back, I don't worry since I don't use it so many times, but I prefer the all-or-nothing approach. So, maybe EfCore for Firebird shoud remain as it is, regarding this feature.

@firebird-automations
Copy link
Author

Commented by: @cincuranet

> At the end, it is on developer shoulder to mantain a consistent behavior of an application if interchangeable provider is required, and perhaps it is better this way..

I agree. But also on the other hand sometimes hiding some implementation/behavior details is handy.

@gilsonjoanelo
Copy link
Contributor

I'm using google translator I was reading the comments, we have the same problems, but we got around it with a migration to structure and another to data, as there are operations that even by isql are not allowed in the same transaction, honestly, I prefer the Firebird peovedor's approach, the all or nothing, because if one part fails, the database does not contain just one part of the migration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants