-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Allow specifying whether computed columns are stored or virtual #6682
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
After searching for this very same subject (persisted computed column), I've stumbled across this issue. After doing some research and some tests, I've came up to the conclusion that this is possible, just not documented (unless I'm being fooled by something). The part that I consider that's missing on the documentation is that the SQL expression that computes the value for the column must contain the PERSISTED keyword.
This generated the following on the migration:
To check on the database whether it is actually persisted I ran the following:
If I had to guess I would say that this expression is replaced on the generated SQL, such as:
|
@DanielSSilva Thanks for this info. Clearing milestone to re-visit in triage. |
Triage: being able to add it to the end of the string like this means that we don't really need to do anything here to support this. Leaving this open to document and add a regression test for. |
I don't know the effort/overload required, but I think it would be more user friendly to be able to pass a boolean as parameter, stating if it's persisted |
@DanielSSilva since this feature is SQL Server-specific, it may make more sense to leave it in the column SQL, which is database-specific anyway... |
Which feature is specific? The whole computed column, or the persisted part? If you are talking about the persisted part, I can agree (although it has to be documented). If the whole |
@DanielSSilva @roji @ajcvickers I was just tripping over a similar issue in that I was trying to set an SQLite computed column and a SQL Server computer column in the model. It looks like under the bonnet these both map back to the same annotation so either overwrite or ignore the second setting. I think it would be very useful to have the ability to include the provider name with
|
@CZEMacLeod Different configuration for different providers is handled by conditionally building different models. For example: modelBuilder
.Entity<User>()
.Property(e => e.Duration_ms)
.HasComputedColumnSql(
Database.IsSqlServer()
? "DATEDIFF(MILLISECOND, 0, duration) PERSISTED"
: "CAST(duration AS int)/1000"); |
@ajcvickers Thanks for the heads up on using the Database extension method. I'm still learning EFCore while porting and maintaining EF6 code so finding the new ways of doing things. The only problem is that I am actually using This means that the Database property is not available, and the type is not exposed on modelBuilder. At the moment, I customize the migration with code similar to
And replace the
If the provider specific variants were stored in the model/snapshot then you could use something like
and the migration would become
But obviously there are work-arounds for the current design. |
@ajcvickers Following up on the last message - it would be useful if the entity types discovered using
Maybe an overload of the method taking an For now I have added a custom interface with a readonly Provider property which I use as the predicate - and have multiple classes, one for each provider. |
If I want a column to stop being computed (with or without persited), I remove the |
@ajcvickers regarding my last comment, should I open a new issue with this question/info? |
@DanielSSilva Yes, please. I try to keep up with comments on existing issues, but it's very easy to miss some. |
FYI PostgreSQL is introducing generated columns in the upcoming version 12. At this point only stored (persisted) generated columns are supported, but on-the-fly computed column support is also expected to land at some point. Unfortunately the SQL Server workaround above - of tacking on ALTER TABLE x ADD COLUMN y INT GENERATED ALWAYS AS (expression) STORED; Since the provider adds the parentheses enclosing the expression, anything tacked at the end will end up inside the parentheses. As a result, from the PostgreSQL side there's definitely motivation for adding a bool flag. |
The situation @roji refers to is also the case for MySQL, the expression should be in between brackets (https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html). If there is consensus on this being a useful addition, I might be able to spend some time on it in the near future. |
@FWest98 thanks for MySQL info. The main thing here is not so much the implementation (which would probably be trivial), as a design proposal for what we should do. One thing to keep in mind is that the SQL Server "default" is a computed column (unless |
For the sake of backwards compatibility, I would personally be in favour of this option indeed. I don't know all SQL dialects, but I think the bool flag in an overload should suffice. I guess the main work in implementing this is actually updating the providers, but even that should be relatively trivial. |
Sqlite also supports both generated column types (VIRTUAL and STORED): https://www.sqlite.org/gencol.html |
See the below table on support across databases. This feature was only recently introduced in PostgreSQL, and as of PG12 only stored columns are supported (not virtual). As a result, EFCore.PG creates computed columns as stored by default, which is contrary to what everyone else is doing. To fix this, I plan on introducing a breaking change for 5.0 which requires users to explicitly specify they want stored columns (until PG adds support for virtual); this would make this issue more important (this is the means for specifying this). So I've submitted a PR for it.
|
The issue
I am using the HasComputedColumnSql extension which basically works for me as expected.
However, I am missing an option to instruct EF to persist the computed values.
Currently the code that is generated for my computed column is:
However, using an option like .Persisted() or a boolean flag like HasComputedColumnSql(string sql, bool persist) I would like to see code generated like this:
It would be an extremely useful feature as it would save time in scripting it manually.
Further technical details
EF Core version: 1.0.0
Operating system: Windows 10
Visual Studio version: VS 2015 Update 3
The text was updated successfully, but these errors were encountered: