Skip to content

Commit

Permalink
Don't write to computed column when table splitting (#21776)
Browse files Browse the repository at this point in the history
Fixes #19176
  • Loading branch information
AndriySvyryd authored Jul 25, 2020
1 parent 35012aa commit 2256528
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/EFCore.Relational/Update/ModificationCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ private IReadOnlyList<ColumnModification> GenerateColumnModifications()
var column = columnMapping.Column;
var isKey = property.IsPrimaryKey();
var isCondition = !adding && (isKey || property.IsConcurrencyToken);
var readValue = entry.IsStoreGenerated(property);
var readValue = state != EntityState.Deleted && entry.IsStoreGenerated(property);
ColumnValuePropagator columnPropagator = null;
if (sharedColumnMap != null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ public virtual bool IsStoreGenerated(IProperty property)
|| HasTemporaryValue(property)
|| HasDefaultValue(property)))
|| (property.ValueGenerated.ForUpdate()
&& EntityState == EntityState.Modified
&& (EntityState == EntityState.Modified || EntityState == EntityState.Deleted)
&& (property.GetAfterSaveBehavior() == PropertySaveBehavior.Ignore
|| !IsModified(property)));

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Infrastructure/ModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,7 @@ protected virtual void ValidateData([NotNull] IModel model, [NotNull] IDiagnosti
{
if (!property.IsNullable
&& ((!property.RequiresValueGenerator()
&& (property.ValueGenerated & ValueGenerated.OnAdd) == 0)
&& !property.ValueGenerated.ForAdd())
|| property.IsPrimaryKey()))
{
throw new InvalidOperationException(
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Metadata/Internal/PropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public static IProperty GetGenerationProperty([NotNull] this IProperty property)
/// values when new entities are added to the context.
/// </summary>
public static bool RequiresValueGenerator([NotNull] this IProperty property)
=> ((property.ValueGenerated & ValueGenerated.OnAdd) == ValueGenerated.OnAdd
=> (property.ValueGenerated.ForAdd()
&& !property.IsForeignKey()
&& property.IsKey())
|| property.GetValueGeneratorFactory() != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,8 @@ protected virtual void OnModelCreating(ModelBuilder modelBuilder)
eb.ToTable("Vehicles");
});

modelBuilder.Entity<Engine>().ToTable("Vehicles");
modelBuilder.Entity<Engine>().ToTable("Vehicles")
.Property(e => e.Computed).ValueGeneratedOnAddOrUpdate();
modelBuilder.Entity<Operator>().ToTable("Vehicles");
modelBuilder.Entity<OperatorDetails>().ToTable("Vehicles");
modelBuilder.Entity<FuelTank>().ToTable("Vehicles");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class Engine
{
public string VehicleName { get; set; }
public string Description { get; set; }
public int Computed { get; set; }
public PoweredVehicle Vehicle { get; set; }

public override bool Equals(object obj)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public override void Can_use_with_redundant_relationships()
@"SELECT [v].[Name], [v].[SeatingCapacity], CASE
WHEN [p].[Name] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [IsPoweredVehicle], [t0].[Name], [t0].[Operator_Name], [t0].[RequiredInt], [t0].[LicenseType], [t0].[IsLicensedOperator], [t3].[Name], [t3].[Type], [t5].[Name], [t5].[Description], [t5].[IsContinuousCombustionEngine], [t5].[IsIntermittentCombustionEngine], [t5].[IsSolidRocket], [t7].[VehicleName], [t7].[Capacity], [t7].[FuelType], [t7].[GrainGeometry], [t7].[IsSolidFuelTank]
END AS [IsPoweredVehicle], [t0].[Name], [t0].[Operator_Name], [t0].[RequiredInt], [t0].[LicenseType], [t0].[IsLicensedOperator], [t3].[Name], [t3].[Type], [t5].[Name], [t5].[Computed], [t5].[Description], [t5].[IsContinuousCombustionEngine], [t5].[IsIntermittentCombustionEngine], [t5].[IsSolidRocket], [t7].[VehicleName], [t7].[Capacity], [t7].[FuelType], [t7].[GrainGeometry], [t7].[IsSolidFuelTank]
FROM [Vehicles] AS [v]
LEFT JOIN [PoweredVehicles] AS [p] ON [v].[Name] = [p].[Name]
LEFT JOIN (
Expand Down Expand Up @@ -66,7 +66,7 @@ WHERE [v3].[RequiredInt] IS NOT NULL
WHERE [v2].[Type] IS NOT NULL
) AS [t3] ON [t0].[Name] = [t3].[Name]
LEFT JOIN (
SELECT [p2].[Name], [p2].[Description], CASE
SELECT [p2].[Name], [p2].[Computed], [p2].[Description], CASE
WHEN [c0].[VehicleName] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [IsContinuousCombustionEngine], CASE
Expand All @@ -86,7 +86,7 @@ INNER JOIN (
FROM [Vehicles] AS [v5]
INNER JOIN [PoweredVehicles] AS [p3] ON [v5].[Name] = [p3].[Name]
) AS [t4] ON [p2].[Name] = [t4].[Name]
WHERE [p2].[Description] IS NOT NULL
WHERE [p2].[Computed] IS NOT NULL
) AS [t5] ON [v].[Name] = [t5].[Name]
LEFT JOIN (
SELECT [c1].[VehicleName], [c1].[Capacity], [c1].[FuelType], [s0].[GrainGeometry], CASE
Expand All @@ -96,7 +96,7 @@ ELSE CAST(0 AS bit)
FROM [CombustionEngines] AS [c1]
LEFT JOIN [SolidFuelTanks] AS [s0] ON [c1].[VehicleName] = [s0].[VehicleName]
INNER JOIN (
SELECT [p4].[Name], [p4].[Description], CASE
SELECT [p4].[Name], [p4].[Computed], [p4].[Description], CASE
WHEN [c3].[VehicleName] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [IsContinuousCombustionEngine], CASE
Expand Down Expand Up @@ -187,7 +187,7 @@ END AS [IsSolidFuelTank]
FROM [CombustionEngines] AS [c]
LEFT JOIN [SolidFuelTanks] AS [s] ON [c].[VehicleName] = [s].[VehicleName]
INNER JOIN (
SELECT [p].[Name], [p].[Description], CASE
SELECT [p].[Name], [p].[Computed], [p].[Description], CASE
WHEN [c1].[VehicleName] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [IsContinuousCombustionEngine], CASE
Expand All @@ -214,7 +214,7 @@ public override void Can_query_shared_derived_nonhierarchy()
@"SELECT [c].[VehicleName], [c].[Capacity], [c].[FuelType]
FROM [CombustionEngines] AS [c]
INNER JOIN (
SELECT [p].[Name], [p].[Description], CASE
SELECT [p].[Name], [p].[Computed], [p].[Description], CASE
WHEN [c1].[VehicleName] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [IsContinuousCombustionEngine], CASE
Expand All @@ -241,7 +241,7 @@ public override void Can_query_shared_derived_nonhierarchy_all_required()
@"SELECT [c].[VehicleName], [c].[Capacity], [c].[FuelType]
FROM [CombustionEngines] AS [c]
INNER JOIN (
SELECT [p].[Name], [p].[Description], CASE
SELECT [p].[Name], [p].[Computed], [p].[Description], CASE
WHEN [c1].[VehicleName] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [IsContinuousCombustionEngine], CASE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.TestModels.TransportationModel;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit.Abstractions;

Expand All @@ -21,7 +22,7 @@ public override void Can_use_with_redundant_relationships()

// TODO: [Name] shouldn't be selected multiple times and no joins are needed
AssertSql(
@"SELECT [v].[Name], [v].[Discriminator], [v].[SeatingCapacity], [t].[Name], [t].[Operator_Discriminator], [t].[Operator_Name], [t].[LicenseType], [t1].[Name], [t1].[Type], [t3].[Name], [t3].[Description], [t3].[Engine_Discriminator], [t7].[Name], [t7].[Capacity], [t7].[FuelTank_Discriminator], [t7].[FuelType], [t7].[GrainGeometry]
@"SELECT [v].[Name], [v].[Discriminator], [v].[SeatingCapacity], [t].[Name], [t].[Operator_Discriminator], [t].[Operator_Name], [t].[LicenseType], [t1].[Name], [t1].[Type], [t3].[Name], [t3].[Computed], [t3].[Description], [t3].[Engine_Discriminator], [t7].[Name], [t7].[Capacity], [t7].[FuelTank_Discriminator], [t7].[FuelType], [t7].[GrainGeometry]
FROM [Vehicles] AS [v]
LEFT JOIN (
SELECT [v0].[Name], [v0].[Operator_Discriminator], [v0].[Operator_Name], [v0].[LicenseType], [v1].[Name] AS [Name0]
Expand All @@ -41,14 +42,14 @@ WHERE [v3].[Operator_Discriminator] IS NOT NULL
WHERE [v2].[Type] IS NOT NULL
) AS [t1] ON [t].[Name] = [t1].[Name]
LEFT JOIN (
SELECT [v5].[Name], [v5].[Description], [v5].[Engine_Discriminator], [t2].[Name] AS [Name0]
SELECT [v5].[Name], [v5].[Computed], [v5].[Description], [v5].[Engine_Discriminator], [t2].[Name] AS [Name0]
FROM [Vehicles] AS [v5]
INNER JOIN (
SELECT [v6].[Name], [v6].[Discriminator], [v6].[SeatingCapacity]
FROM [Vehicles] AS [v6]
WHERE [v6].[Discriminator] = N'PoweredVehicle'
) AS [t2] ON [v5].[Name] = [t2].[Name]
WHERE [v5].[Engine_Discriminator] IS NOT NULL
WHERE [v5].[Engine_Discriminator] IS NOT NULL AND [v5].[Computed] IS NOT NULL
) AS [t3] ON [v].[Name] = [t3].[Name]
LEFT JOIN (
SELECT [v7].[Name], [v7].[Capacity], [v7].[FuelTank_Discriminator], [v7].[FuelType], [v7].[GrainGeometry]
Expand All @@ -63,7 +64,7 @@ WHERE [v7].[FuelTank_Discriminator] IS NOT NULL
SELECT [v9].[Name], [v9].[Capacity], [v9].[FuelTank_Discriminator], [v9].[FuelType], [v9].[GrainGeometry]
FROM [Vehicles] AS [v9]
INNER JOIN (
SELECT [v10].[Name], [v10].[Description], [v10].[Engine_Discriminator], [t5].[Name] AS [Name0]
SELECT [v10].[Name], [v10].[Computed], [v10].[Description], [v10].[Engine_Discriminator], [t5].[Name] AS [Name0]
FROM [Vehicles] AS [v10]
INNER JOIN (
SELECT [v11].[Name], [v11].[Discriminator], [v11].[SeatingCapacity]
Expand Down Expand Up @@ -145,7 +146,7 @@ WHERE [v].[FuelTank_Discriminator] IS NOT NULL
SELECT [v1].[Name], [v1].[Capacity], [v1].[FuelTank_Discriminator], [v1].[FuelType], [v1].[GrainGeometry]
FROM [Vehicles] AS [v1]
INNER JOIN (
SELECT [v2].[Name], [v2].[Description], [v2].[Engine_Discriminator], [t0].[Name] AS [Name0]
SELECT [v2].[Name], [v2].[Computed], [v2].[Description], [v2].[Engine_Discriminator], [t0].[Name] AS [Name0]
FROM [Vehicles] AS [v2]
INNER JOIN (
SELECT [v3].[Name], [v3].[Discriminator], [v3].[SeatingCapacity]
Expand Down Expand Up @@ -174,7 +175,7 @@ WHERE [v].[FuelType] IS NOT NULL OR [v].[Capacity] IS NOT NULL
SELECT [v1].[Name], [v1].[Capacity], [v1].[FuelType]
FROM [Vehicles] AS [v1]
INNER JOIN (
SELECT [v2].[Name], [v2].[Description], [v2].[Engine_Discriminator], [t0].[Name] AS [Name0]
SELECT [v2].[Name], [v2].[Computed], [v2].[Description], [v2].[Engine_Discriminator], [t0].[Name] AS [Name0]
FROM [Vehicles] AS [v2]
INNER JOIN (
SELECT [v3].[Name], [v3].[Discriminator], [v3].[SeatingCapacity]
Expand Down Expand Up @@ -203,7 +204,7 @@ WHERE [v].[FuelType] IS NOT NULL AND [v].[Capacity] IS NOT NULL
SELECT [v1].[Name], [v1].[Capacity], [v1].[FuelType]
FROM [Vehicles] AS [v1]
INNER JOIN (
SELECT [v2].[Name], [v2].[Description], [v2].[Engine_Discriminator], [t0].[Name] AS [Name0]
SELECT [v2].[Name], [v2].[Computed], [v2].[Description], [v2].[Engine_Discriminator], [t0].[Name] AS [Name0]
FROM [Vehicles] AS [v2]
INNER JOIN (
SELECT [v3].[Name], [v3].[Discriminator], [v3].[SeatingCapacity]
Expand Down Expand Up @@ -264,5 +265,13 @@ WHERE [v0].[Operator_Discriminator] IS NOT NULL
) AS [t] ON [v].[Name] = [t].[Name]
WHERE [v].[Name] = N'Trek Pro Fit Madone 6 Series'");
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<Engine>().ToTable("Vehicles")
.Property(e => e.Computed).HasComputedColumnSql("1", stored: true);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.TestModels.TransportationModel;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit.Abstractions;

Expand All @@ -13,6 +14,14 @@ public TableSplittingSqliteTest(ITestOutputHelper testOutputHelper)
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<Engine>().ToTable("Vehicles")
.Property(e => e.Computed).HasComputedColumnSql("1");
}

protected override ITestStoreFactory TestStoreFactory => SqliteTestStoreFactory.Instance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,7 @@ public void Indexer_property_removes_existing_shadow_property_for_higher_source(
}

[ConditionalFact]
public void Indexed_property_throws_when_entityType_is_not_indexer()
public void Indexer_property_throws_when_entityType_is_not_indexer()
{
var modelBuilder = CreateModelBuilder();
var entityBuilder = modelBuilder.Entity(typeof(Order), ConfigurationSource.Explicit);
Expand Down

0 comments on commit 2256528

Please sign in to comment.