Updated computed columns property may be inverted with INSTEAD OF triggers
See original GitHub issueEF Core version: 5.0.7 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 5.0 Operating system: W10 x64 IDE: VS 2019 16.10.4
Hello,
I’m having an issue with INSTEAD OF
triggers and computed columns on SQL Server.
Here is a sample model :
public class MyTable
{
public long Identifier { get; set; }
public string NotComputedColumn { get; set; }
public string ComputedColumn1 { get; set; }
public string ComputedColumn2 { get; set; }
}
public class MyContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyTable>(entity =>
{
entity.ToTable(nameof(MyTable));
entity.HasKey(e => e.Identifier);
entity.Property(e => e.ComputedColumn1 )
.HasComputedColumnSql();
entity.Property(e => e.ComputedColumn2 )
.HasComputedColumnSql();
});
base.OnModelCreating(modelBuilder);
}
}
When using computed columns with HasComputedColumnSql
on a table, EF Core add the columns to a generated SELECT
query after the INSERT
statement. By example :
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Table] ([NotComputedColumn])
VALUES (@p0);
SELECT [Identifier], [ComputedColumn1], [ComputedColumn2]
FROM [Contact]
WHERE @@ROWCOUNT = 1 AND [Identifier] = scope_identity();
',N'@p0 nvarchar(4000)',@p0='A value'
EF have this logic :
- insert data
- select keys and computed columns
- take the first results set of the data reader
- update the POCO with readed data
All my tables have INSTEAD OF INSERT
triggers like this :
CREATE TRIGGER [dbo].[MyTableInsteadOfInsert] ON [dbo].[MyTable] INSTEAD OF INSERT AS
BEGIN
CREATE TABLE #TempTable (
[Identifier] BIGINT
,[ComputedColumn1] VARCHAR(100)
,[ComputedColumn2] VARCHAR(100)
)
--Pre insert SQL code
INSERT INTO MyTable
(
NotComputedColumn
)
OUTPUT
inserted.Identifier
,inserted.ComputedColumn1
,inserted.ComputedColumn2
INTO
#TempTable
--This statement is the one readed by EF Core since it will be the first result set in the data reader. The generated SELECT by EF is replaced by this one.
SELECT
t0.Identifier
,t0.ComputedColumn1 --NOTE : Changing column order is causing the described issue, see below
,t0.ComputedColumn2
FROM
#TempTable AS t0
--Post insert code
END
As you can see, the trigger make a similar SELECT
statement just after the INSERT INTO
. I do this in order to be sure that EF read this result set and not another one that may be generated by another SELECT
statement in the post insert code section.
My issue is that EF Core do not use the column name when reading the select results, EF use the result columns order.
This lead to an issue if in my SELECT
statement the ComputedColumn2
column is projected prior the ComputedColumn1
column.
It seams that EF Core use the alphabetic order so it works if my trigger respect this order too but this is a breaking changes from the Entity Framework V4 (yes, I know, it’s old…).
Is there any chance you can modify this ?
Thanks a lot
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (3 by maintainers)
Note from triage: discussed with team and agreed that this change is by-design.
@JeremyLikness This could be something to mention in the porting guide.
I understand the change was made for optimisation and yes I can change the order of the columns in the trigger because this changes will not break currently working EF Framework V4 but since there is no warning or error, this could lead to potential bugs in production if some triggers are not modified and EF Core compliants.