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

add AddByteColumn to add tinyint to the database table. #2605

Merged
merged 1 commit into from
Feb 21, 2023

Conversation

Behnam-Emamian
Copy link
Contributor

Added AddByteColumn method to BaseEntityBuilder class to generate tinyint field in the database table.

@dnfadmin
Copy link

dnfadmin commented Feb 19, 2023

CLA assistant check
All CLA requirements met.

@sbwalker
Copy link
Member

sbwalker commented Feb 20, 2023

Oqtane supports 4 database engines - SQL Server, SQLite, mySQL, PostgreSQL. The BaseEntityBuilder only included data types which were supported by all of these databases. Do you know if byte is supported by all of these databases?

@Behnam-Emamian
Copy link
Contributor Author

EF Core SQL Server Provider (Microsoft.EntityFrameworkCore.SqlServer) is using Microsoft.Data.SqlClient to connect to sql server database and supports byte as tinyint field.

EF Core Sqlite Provider (Microsoft.EntityFrameworkCore.Sqlite) is using Microsoft.Data.Sqlite to connect to sqlite database and supports byte as INTEGER field.
https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/types

EF Core MySQL Provider (MySql.EntityFrameworkCore) is using MySQL Connector/NET to connect to MySql database and supports byte as tinyint unsigned

EF Core PostgreSQL Provider (Npgsql.EntityFrameworkCore.PostgreSQL) is using Npgsql to connect to PostgreSql database and supports byte as smallint
https://www.npgsql.org/doc/types/basic.html

@Behnam-Emamian
Copy link
Contributor Author

I have tested sql server and it is ok, I can see the tinyint field in the table.

I am testing sqlite but I cannot install oqtane 3.3.1 on sqlite, it shows an error and stops in installation wizard.

I will test MySql and PostgreSQL after finding the sqlite bug.

@Behnam-Emamian
Copy link
Contributor Author

Behnam-Emamian commented Feb 21, 2023

It cannot create the site when the db is sqlite
FYI: there is no code change in the source code

image

@Behnam-Emamian
Copy link
Contributor Author

Behnam-Emamian commented Feb 21, 2023

Ok, found the bug

I can see in the folder migration, logical delete fields has been added to the table:
image

but the entity does not have them:
image

then we receive a null exception error in inserting a folder record in the sqlite folder table.

and it is strange how it is working for SQL Server!!! wow, Folder table in sql server does not have IDeletable columns!?!?!?
image

@Behnam-Emamian
Copy link
Contributor Author

I have found this migration RemoveFolderFileDeletableColumns which I can see has been run in sql server and sqlite in __EFMigrationsHistory

but the IDeletable columns are still there in sqlite folder table

@Behnam-Emamian
Copy link
Contributor Author

nice, DropColumn is not working in sqlite :-D
dotnet/efcore#329

Solution:
https://stackoverflow.com/questions/41902905/ef-core-dropping-a-column-workaround-sqlite

I can fix it if you are ok!

@sbwalker
Copy link
Member

sbwalker commented Feb 21, 2023

@Behnam-Emamian the issue with SQLite was already reported and fixed in #2584

@Behnam-Emamian
Copy link
Contributor Author

@Behnam-Emamian the issue with SQLite was already reported and fixed in #2584

It can be the option 3, like copy from old table to a temporary table without those columns that we need to delete and then delete the old table and renew the temporary table to old table.

@sbwalker
Copy link
Member

I previously investigated the StackOverflow link you provided but the solution is rather ugly and difficult to integrate. The goal in the Oqtane database abstraction is to keep the core API simple and generic and try to avoid conditional logic as much as possible. Any differences in database engine implementations should be in the providers - which is why the DropColumn method in the SQLite provider is overridden (as well as a few others). In order to include logic similar to the StackOverflow article in the SQLite provider, the DropColumn method would need a LOT more context (since it needs to recreate the table, etc...) but this context would only be applicable to SQLite. As a result I opted for a simpler approach.

@sbwalker
Copy link
Member

sbwalker commented Feb 21, 2023

In case my explanation is not clear, a developer using Oqtane should be able to use simple/generic methods when interacting with the database. Specifically in their own code they should be able to specify DropColumn("ColumnName") and it should "work" on all supported databases. They should not not have to write DropColumn("ColumnName", "Create New Table Logic", "Migrate Data Logic", etc...) as the extra context parameters are only applicable to a specific database (SQLite).

@sbwalker
Copy link
Member

sbwalker commented Feb 21, 2023

Based on your research it appears that all of the databases support tinyint (or at least map it to some other internal data type). So I can merge this PR.

@Behnam-Emamian
Copy link
Contributor Author

In case my explanation is not clear, a developer using Oqtane should be able to use simple/generic methods when interacting with the database. Specifically in their own code they should be able to specify DropColumn("ColumnName") and it should "work" on all supported databases. They should not not have to write DropColumn("ColumnName", "Create New Table Logic", "Migrate Data Logic", etc...) as the extra context parameters are only applicable to a specific database (SQLite).

I am completly agree but this is the sqlite limitation and if user really need to delete column and save the current data, there is no simple solution like DropColumn("ColumnName") unfortunately.

I have checked the Microsoft.Data.Sqlite solution for this limitation, it is "rebuilding the table" which I believe it is not a good solution as the data will be lost.

https://learn.microsoft.com/en-us/ef/core/providers/sqlite/limitations?toc=%2Fdotnet%2Fnavigate%2Fdata-access%2Ftoc.json&bc=%2Fdotnet%2Fbreadcrumb%2Ftoc.json

@sbwalker
Copy link
Member

I am completly agree but this is the sqlite limitation and if user really need to delete column and save the current data, there is no simple solution like DropColumn("ColumnName") unfortunately.

Correct - there is no simple solution at the database level due to differences between database engines - so the simple solution is to orphan the column in the SQLite database (this approach is actually very common in the NoSQL database community).

@sbwalker sbwalker merged commit 71dd00d into oqtane:dev Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants