Remove unsupported tests
parent
b3ac6b70c1
commit
7fec659065
@ -1,444 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.TestModels.StoreValueGenerationModel;
|
|
||||||
using Microsoft.EntityFrameworkCore.TestUtilities;
|
|
||||||
using Microsoft.EntityFrameworkCore.Update;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore.Jet.FunctionalTests.Update;
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
public class StoreValueGenerationSequenceJetTest : StoreValueGenerationTestBase<
|
|
||||||
StoreValueGenerationSequenceJetTest.StoreValueGenerationSequenceJetFixture>
|
|
||||||
{
|
|
||||||
public StoreValueGenerationSequenceJetTest(
|
|
||||||
StoreValueGenerationSequenceJetFixture fixture,
|
|
||||||
ITestOutputHelper testOutputHelper)
|
|
||||||
: base(fixture)
|
|
||||||
{
|
|
||||||
Fixture.TestSqlLoggerFactory.Clear();
|
|
||||||
// Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ShouldCreateImplicitTransaction(
|
|
||||||
EntityState firstOperationType,
|
|
||||||
EntityState? secondOperationType,
|
|
||||||
GeneratedValues generatedValues,
|
|
||||||
bool withSameEntityType)
|
|
||||||
{
|
|
||||||
// For multiple operations, we specifically optimize multiple insertions of the same entity type with a single command (e.g. MERGE)
|
|
||||||
// (as long as there are writable columns)
|
|
||||||
if (firstOperationType is EntityState.Added
|
|
||||||
&& secondOperationType is EntityState.Added
|
|
||||||
&& withSameEntityType
|
|
||||||
&& generatedValues != GeneratedValues.All)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other single operations should never be in a transaction (always executed in a single SQL command)
|
|
||||||
return secondOperationType is not null;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Single operation
|
|
||||||
|
|
||||||
public override async Task Add_with_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_with_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='1000'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithSomeDatabaseGenerated] ([Data2])
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1]
|
|
||||||
VALUES (@p0);
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add_with_no_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_with_no_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='100'
|
|
||||||
@p1='1000'
|
|
||||||
@p2='1000'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithNoDatabaseGenerated] ([Id], [Data1], [Data2])
|
|
||||||
VALUES (@p0, @p1, @p2);
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add_with_all_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_with_all_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithAllDatabaseGenerated]
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1], INSERTED.[Data2]
|
|
||||||
DEFAULT VALUES;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Modify_with_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Modify_with_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p1='5'
|
|
||||||
@p0='1000'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [WithSomeDatabaseGenerated] SET [Data2] = @p0
|
|
||||||
OUTPUT INSERTED.[Data1]
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Modify_with_no_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Modify_with_no_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p2='1'
|
|
||||||
@p0='1000'
|
|
||||||
@p1='1000'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [WithNoDatabaseGenerated] SET [Data1] = @p0, [Data2] = @p1
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p2;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Delete(bool async)
|
|
||||||
{
|
|
||||||
await base.Delete(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='5'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
DELETE FROM [WithSomeDatabaseGenerated]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p0;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Single operation
|
|
||||||
|
|
||||||
#region Same two operations with same entity type
|
|
||||||
|
|
||||||
public override async Task Add_Add_with_same_entity_type_and_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_Add_with_same_entity_type_and_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='1000'
|
|
||||||
@p1='1001'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
MERGE [WithSomeDatabaseGenerated] USING (
|
|
||||||
VALUES (@p0, 0),
|
|
||||||
(@p1, 1)) AS i ([Data2], _Position) ON 1=0
|
|
||||||
WHEN NOT MATCHED THEN
|
|
||||||
INSERT ([Data2])
|
|
||||||
VALUES (i.[Data2])
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1], i._Position;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add_Add_with_same_entity_type_and_no_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_Add_with_same_entity_type_and_no_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='100'
|
|
||||||
@p1='1000'
|
|
||||||
@p2='1000'
|
|
||||||
@p3='101'
|
|
||||||
@p4='1001'
|
|
||||||
@p5='1001'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithNoDatabaseGenerated] ([Id], [Data1], [Data2])
|
|
||||||
VALUES (@p0, @p1, @p2),
|
|
||||||
(@p3, @p4, @p5);
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add_Add_with_same_entity_type_and_all_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_Add_with_same_entity_type_and_all_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
DECLARE @inserted0 TABLE ([Id] int);
|
|
||||||
INSERT INTO [WithAllDatabaseGenerated] ([Id])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
INTO @inserted0
|
|
||||||
VALUES (DEFAULT),
|
|
||||||
(DEFAULT);
|
|
||||||
SELECT [t].[Id], [t].[Data1], [t].[Data2] FROM [WithAllDatabaseGenerated] t
|
|
||||||
INNER JOIN @inserted0 i ON ([t].[Id] = [i].[Id]);
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Modify_Modify_with_same_entity_type_and_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Modify_Modify_with_same_entity_type_and_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p1='5'
|
|
||||||
@p0='1000'
|
|
||||||
@p3='6'
|
|
||||||
@p2='1001'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [WithSomeDatabaseGenerated] SET [Data2] = @p0
|
|
||||||
OUTPUT INSERTED.[Data1]
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
UPDATE [WithSomeDatabaseGenerated] SET [Data2] = @p2
|
|
||||||
OUTPUT INSERTED.[Data1]
|
|
||||||
WHERE [Id] = @p3;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Modify_Modify_with_same_entity_type_and_no_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Modify_Modify_with_same_entity_type_and_no_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p2='1'
|
|
||||||
@p0='1000'
|
|
||||||
@p1='1000'
|
|
||||||
@p5='2'
|
|
||||||
@p3='1001'
|
|
||||||
@p4='1001'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [WithNoDatabaseGenerated] SET [Data1] = @p0, [Data2] = @p1
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p2;
|
|
||||||
UPDATE [WithNoDatabaseGenerated] SET [Data1] = @p3, [Data2] = @p4
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p5;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Delete_Delete_with_same_entity_type(bool async)
|
|
||||||
{
|
|
||||||
await base.Delete_Delete_with_same_entity_type(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='5'
|
|
||||||
@p1='6'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
DELETE FROM [WithSomeDatabaseGenerated]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p0;
|
|
||||||
DELETE FROM [WithSomeDatabaseGenerated]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Same two operations with same entity type
|
|
||||||
|
|
||||||
#region Same two operations with different entity types
|
|
||||||
|
|
||||||
public override async Task Add_Add_with_different_entity_types_and_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_Add_with_different_entity_types_and_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='1000'
|
|
||||||
@p1='1001'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithSomeDatabaseGenerated] ([Data2])
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1]
|
|
||||||
VALUES (@p0);
|
|
||||||
INSERT INTO [WithSomeDatabaseGenerated2] ([Data2])
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1]
|
|
||||||
VALUES (@p1);
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add_Add_with_different_entity_types_and_no_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_Add_with_different_entity_types_and_no_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='100'
|
|
||||||
@p1='1000'
|
|
||||||
@p2='1000'
|
|
||||||
@p3='101'
|
|
||||||
@p4='1001'
|
|
||||||
@p5='1001'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithNoDatabaseGenerated] ([Id], [Data1], [Data2])
|
|
||||||
VALUES (@p0, @p1, @p2);
|
|
||||||
INSERT INTO [WithNoDatabaseGenerated2] ([Id], [Data1], [Data2])
|
|
||||||
VALUES (@p3, @p4, @p5);
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add_Add_with_different_entity_types_and_all_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Add_Add_with_different_entity_types_and_all_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [WithAllDatabaseGenerated]
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1], INSERTED.[Data2]
|
|
||||||
DEFAULT VALUES;
|
|
||||||
INSERT INTO [WithAllDatabaseGenerated2]
|
|
||||||
OUTPUT INSERTED.[Id], INSERTED.[Data1], INSERTED.[Data2]
|
|
||||||
DEFAULT VALUES;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Modify_Modify_with_different_entity_types_and_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Modify_Modify_with_different_entity_types_and_generated_values(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p1='5'
|
|
||||||
@p0='1000'
|
|
||||||
@p3='8'
|
|
||||||
@p2='1001'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [WithSomeDatabaseGenerated] SET [Data2] = @p0
|
|
||||||
OUTPUT INSERTED.[Data1]
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
UPDATE [WithSomeDatabaseGenerated2] SET [Data2] = @p2
|
|
||||||
OUTPUT INSERTED.[Data1]
|
|
||||||
WHERE [Id] = @p3;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Modify_Modify_with_different_entity_types_and_no_generated_values(bool async)
|
|
||||||
{
|
|
||||||
await base.Modify_Modify_with_different_entity_types_and_no_generated_values(async);
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p2='1'
|
|
||||||
@p0='1000'
|
|
||||||
@p1='1000'
|
|
||||||
@p5='2'
|
|
||||||
@p3='1001'
|
|
||||||
@p4='1001'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [WithNoDatabaseGenerated] SET [Data1] = @p0, [Data2] = @p1
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p2;
|
|
||||||
UPDATE [WithNoDatabaseGenerated2] SET [Data1] = @p3, [Data2] = @p4
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p5;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Delete_Delete_with_different_entity_types(bool async)
|
|
||||||
{
|
|
||||||
await base.Delete_Delete_with_different_entity_types(async);
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0='5'
|
|
||||||
@p1='8'
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
DELETE FROM [WithSomeDatabaseGenerated]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p0;
|
|
||||||
DELETE FROM [WithSomeDatabaseGenerated2]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Same two operations with different entity types
|
|
||||||
|
|
||||||
protected override async Task Test(
|
|
||||||
EntityState firstOperationType,
|
|
||||||
EntityState? secondOperationType,
|
|
||||||
GeneratedValues generatedValues,
|
|
||||||
bool async,
|
|
||||||
bool withSameEntityType = true)
|
|
||||||
{
|
|
||||||
await base.Test(firstOperationType, secondOperationType, generatedValues, async, withSameEntityType);
|
|
||||||
|
|
||||||
if (!ShouldCreateImplicitTransaction(firstOperationType, secondOperationType, generatedValues, withSameEntityType))
|
|
||||||
{
|
|
||||||
Assert.Contains("SET IMPLICIT_TRANSACTIONS OFF", Fixture.TestSqlLoggerFactory.SqlStatements[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StoreValueGenerationSequenceJetFixture : StoreValueGenerationJetFixtureBase
|
|
||||||
{
|
|
||||||
protected override string StoreName
|
|
||||||
=> "StoreValueGenerationSequenceTest";
|
|
||||||
|
|
||||||
protected override ITestStoreFactory TestStoreFactory
|
|
||||||
=> JetTestStoreFactory.Instance;
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder, context);
|
|
||||||
|
|
||||||
modelBuilder.HasSequence<int>("Ids");
|
|
||||||
|
|
||||||
foreach (var name in new[]
|
|
||||||
{
|
|
||||||
nameof(StoreValueGenerationContext.WithSomeDatabaseGenerated),
|
|
||||||
nameof(StoreValueGenerationContext.WithSomeDatabaseGenerated2),
|
|
||||||
nameof(StoreValueGenerationContext.WithAllDatabaseGenerated),
|
|
||||||
nameof(StoreValueGenerationContext.WithAllDatabaseGenerated2)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
modelBuilder
|
|
||||||
.SharedTypeEntity<StoreValueGenerationData>(name)
|
|
||||||
.Property(w => w.Id)
|
|
||||||
.HasDefaultValueSql("NEXT VALUE FOR [Ids]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
||||||
using Microsoft.EntityFrameworkCore.TestModels.UpdatesModel;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore.Jet.FunctionalTests;
|
|
||||||
|
|
||||||
public class UpdatesJetTPCTest : UpdatesJetTestBase<UpdatesJetTPCTest.UpdatesJetTPCFixture>
|
|
||||||
{
|
|
||||||
// ReSharper disable once UnusedParameter.Local
|
|
||||||
public UpdatesJetTPCTest(UpdatesJetTPCFixture fixture, ITestOutputHelper testOutputHelper)
|
|
||||||
: base(fixture, testOutputHelper)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save_with_shared_foreign_key()
|
|
||||||
{
|
|
||||||
base.Save_with_shared_foreign_key();
|
|
||||||
|
|
||||||
AssertContainsSql(
|
|
||||||
@"@p0=NULL (Size = 8000) (DbType = Binary)
|
|
||||||
@p1='ProductWithBytes' (Nullable = false) (Size = 4000)
|
|
||||||
@p2=NULL (Size = 4000)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [ProductBase] ([Bytes], [Discriminator], [ProductWithBytes_Name])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
VALUES (@p0, @p1, @p2);",
|
|
||||||
@"@p0=NULL (Size = 4000)
|
|
||||||
@p1='777'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [SpecialCategory] ([Name], [PrincipalId])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
VALUES (@p0, @p1);");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save_replaced_principal()
|
|
||||||
{
|
|
||||||
base.Save_replaced_principal();
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
SELECT TOP(2) [t].[Id], [t].[Name], [t].[PrincipalId], [t].[Discriminator]
|
|
||||||
FROM (
|
|
||||||
SELECT [c].[Id], [c].[Name], [c].[PrincipalId], N'Category' AS [Discriminator]
|
|
||||||
FROM [Categories] AS [c]
|
|
||||||
UNION ALL
|
|
||||||
SELECT [s].[Id], [s].[Name], [s].[PrincipalId], N'SpecialCategory' AS [Discriminator]
|
|
||||||
FROM [SpecialCategory] AS [s]
|
|
||||||
) AS [t]
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@__category_PrincipalId_0='778' (Nullable = true)
|
|
||||||
|
|
||||||
SELECT [p].[Id], [p].[Discriminator], [p].[DependentId], [p].[Name], [p].[Price]
|
|
||||||
FROM [ProductBase] AS [p]
|
|
||||||
WHERE [p].[Discriminator] = N'Product' AND [p].[DependentId] = @__category_PrincipalId_0
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p1='1'
|
|
||||||
@p0='New Category' (Size = 4000)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [Categories] SET [Name] = @p0
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
SELECT TOP(2) [t].[Id], [t].[Name], [t].[PrincipalId], [t].[Discriminator]
|
|
||||||
FROM (
|
|
||||||
SELECT [c].[Id], [c].[Name], [c].[PrincipalId], N'Category' AS [Discriminator]
|
|
||||||
FROM [Categories] AS [c]
|
|
||||||
UNION ALL
|
|
||||||
SELECT [s].[Id], [s].[Name], [s].[PrincipalId], N'SpecialCategory' AS [Discriminator]
|
|
||||||
FROM [SpecialCategory] AS [s]
|
|
||||||
) AS [t]
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@__category_PrincipalId_0='778' (Nullable = true)
|
|
||||||
|
|
||||||
SELECT [p].[Id], [p].[Discriminator], [p].[DependentId], [p].[Name], [p].[Price]
|
|
||||||
FROM [ProductBase] AS [p]
|
|
||||||
WHERE [p].[Discriminator] = N'Product' AND [p].[DependentId] = @__category_PrincipalId_0
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdatesJetTPCFixture : UpdatesJetFixtureBase
|
|
||||||
{
|
|
||||||
protected override string StoreName
|
|
||||||
=> "UpdateTestTPC";
|
|
||||||
|
|
||||||
public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder)
|
|
||||||
=> base.AddOptions(builder).ConfigureWarnings(
|
|
||||||
w =>
|
|
||||||
{
|
|
||||||
w.Log(RelationalEventId.ForeignKeyTpcPrincipalWarning);
|
|
||||||
});
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder, context);
|
|
||||||
|
|
||||||
modelBuilder.Entity<Category>().UseTpcMappingStrategy();
|
|
||||||
// modelBuilder.Entity<GiftObscurer>().UseTpcMappingStrategy(); Issue #29874
|
|
||||||
modelBuilder.Entity<LiftObscurer>().UseTpcMappingStrategy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.TestModels.UpdatesModel;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore.Jet.FunctionalTests;
|
|
||||||
|
|
||||||
public class UpdatesJetTPTTest : UpdatesJetTestBase<UpdatesJetTPTTest.UpdatesJetTPTFixture>
|
|
||||||
{
|
|
||||||
// ReSharper disable once UnusedParameter.Local
|
|
||||||
public UpdatesJetTPTTest(UpdatesJetTPTFixture fixture, ITestOutputHelper testOutputHelper)
|
|
||||||
: base(fixture, testOutputHelper)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory(Skip = "Issue #29874. Skipped because the database is in a bad state, but the test may or may not fail.")]
|
|
||||||
public override Task Can_change_type_of_pk_to_pk_dependent_by_replacing_with_new_dependent(bool async)
|
|
||||||
=> Task.CompletedTask;
|
|
||||||
|
|
||||||
public override void Save_with_shared_foreign_key()
|
|
||||||
{
|
|
||||||
base.Save_with_shared_foreign_key();
|
|
||||||
|
|
||||||
AssertContainsSql(
|
|
||||||
@"@p0=NULL (Size = 8000) (DbType = Binary)
|
|
||||||
@p1='ProductWithBytes' (Nullable = false) (Size = 4000)
|
|
||||||
@p2=NULL (Size = 4000)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [ProductBase] ([Bytes], [Discriminator], [ProductWithBytes_Name])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
VALUES (@p0, @p1, @p2);",
|
|
||||||
@"@p0=NULL (Size = 4000)
|
|
||||||
@p1='777'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [Categories] ([Name], [PrincipalId])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
VALUES (@p0, @p1);");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save_replaced_principal()
|
|
||||||
{
|
|
||||||
base.Save_replaced_principal();
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
SELECT TOP(2) [c].[Id], [c].[Name], [c].[PrincipalId], CASE
|
|
||||||
WHEN [s].[Id] IS NOT NULL THEN N'SpecialCategory'
|
|
||||||
END AS [Discriminator]
|
|
||||||
FROM [Categories] AS [c]
|
|
||||||
LEFT JOIN [SpecialCategory] AS [s] ON [c].[Id] = [s].[Id]
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@__category_PrincipalId_0='778' (Nullable = true)
|
|
||||||
|
|
||||||
SELECT [p].[Id], [p].[Discriminator], [p].[DependentId], [p].[Name], [p].[Price]
|
|
||||||
FROM [ProductBase] AS [p]
|
|
||||||
WHERE [p].[Discriminator] = N'Product' AND [p].[DependentId] = @__category_PrincipalId_0
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p1='1'
|
|
||||||
@p0='New Category' (Size = 4000)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [Categories] SET [Name] = @p0
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
SELECT TOP(2) [c].[Id], [c].[Name], [c].[PrincipalId], CASE
|
|
||||||
WHEN [s].[Id] IS NOT NULL THEN N'SpecialCategory'
|
|
||||||
END AS [Discriminator]
|
|
||||||
FROM [Categories] AS [c]
|
|
||||||
LEFT JOIN [SpecialCategory] AS [s] ON [c].[Id] = [s].[Id]
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@__category_PrincipalId_0='778' (Nullable = true)
|
|
||||||
|
|
||||||
SELECT [p].[Id], [p].[Discriminator], [p].[DependentId], [p].[Name], [p].[Price]
|
|
||||||
FROM [ProductBase] AS [p]
|
|
||||||
WHERE [p].[Discriminator] = N'Product' AND [p].[DependentId] = @__category_PrincipalId_0
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdatesJetTPTFixture : UpdatesJetFixtureBase
|
|
||||||
{
|
|
||||||
protected override string StoreName
|
|
||||||
=> "UpdateTestTPT";
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder, context);
|
|
||||||
|
|
||||||
modelBuilder.Entity<Category>().UseTptMappingStrategy();
|
|
||||||
modelBuilder.Entity<GiftObscurer>().UseTptMappingStrategy();
|
|
||||||
modelBuilder.Entity<LiftObscurer>().UseTptMappingStrategy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore.Jet.FunctionalTests;
|
|
||||||
|
|
||||||
public class UpdatesJetTest : UpdatesJetTestBase<UpdatesJetTest.UpdatesJetFixture>
|
|
||||||
{
|
|
||||||
// ReSharper disable once UnusedParameter.Local
|
|
||||||
public UpdatesJetTest(UpdatesJetFixture fixture, ITestOutputHelper testOutputHelper)
|
|
||||||
: base(fixture, testOutputHelper)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save_with_shared_foreign_key()
|
|
||||||
{
|
|
||||||
base.Save_with_shared_foreign_key();
|
|
||||||
|
|
||||||
AssertContainsSql(
|
|
||||||
@"@p0=NULL (Size = 8000) (DbType = Binary)
|
|
||||||
@p1='ProductWithBytes' (Nullable = false) (Size = 4000)
|
|
||||||
@p2=NULL (Size = 4000)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [ProductBase] ([Bytes], [Discriminator], [ProductWithBytes_Name])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
VALUES (@p0, @p1, @p2);",
|
|
||||||
@"@p0='SpecialCategory' (Nullable = false) (Size = 4000)
|
|
||||||
@p1=NULL (Size = 4000)
|
|
||||||
@p2='777'
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [Categories] ([Discriminator], [Name], [PrincipalId])
|
|
||||||
OUTPUT INSERTED.[Id]
|
|
||||||
VALUES (@p0, @p1, @p2);");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save_replaced_principal()
|
|
||||||
{
|
|
||||||
base.Save_replaced_principal();
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
SELECT TOP(2) [c].[Id], [c].[Discriminator], [c].[Name], [c].[PrincipalId]
|
|
||||||
FROM [Categories] AS [c]
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@__category_PrincipalId_0='778' (Nullable = true)
|
|
||||||
|
|
||||||
SELECT [p].[Id], [p].[Discriminator], [p].[DependentId], [p].[Name], [p].[Price]
|
|
||||||
FROM [ProductBase] AS [p]
|
|
||||||
WHERE [p].[Discriminator] = N'Product' AND [p].[DependentId] = @__category_PrincipalId_0
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p1='1'
|
|
||||||
@p0='New Category' (Size = 4000)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
UPDATE [Categories] SET [Name] = @p0
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [Id] = @p1;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
SELECT TOP(2) [c].[Id], [c].[Discriminator], [c].[Name], [c].[PrincipalId]
|
|
||||||
FROM [Categories] AS [c]
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@__category_PrincipalId_0='778' (Nullable = true)
|
|
||||||
|
|
||||||
SELECT [p].[Id], [p].[Discriminator], [p].[DependentId], [p].[Name], [p].[Price]
|
|
||||||
FROM [ProductBase] AS [p]
|
|
||||||
WHERE [p].[Discriminator] = N'Product' AND [p].[DependentId] = @__category_PrincipalId_0
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdatesJetFixture : UpdatesJetFixtureBase
|
|
||||||
{
|
|
||||||
protected override string StoreName
|
|
||||||
=> "UpdateTest";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,288 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.TestModels.UpdatesModel;
|
|
||||||
using Microsoft.EntityFrameworkCore.TestUtilities;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore.Jet.FunctionalTests;
|
|
||||||
|
|
||||||
public abstract class UpdatesJetTestBase<TFixture> : UpdatesRelationalTestBase<TFixture>
|
|
||||||
where TFixture : UpdatesJetTestBase<TFixture>.UpdatesJetFixtureBase
|
|
||||||
{
|
|
||||||
// ReSharper disable once UnusedParameter.Local
|
|
||||||
public UpdatesJetTestBase(TFixture fixture, ITestOutputHelper testOutputHelper)
|
|
||||||
: base(fixture)
|
|
||||||
{
|
|
||||||
//Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
|
|
||||||
Fixture.TestSqlLoggerFactory.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Can_add_and_remove_self_refs()
|
|
||||||
{
|
|
||||||
Fixture.ResetIdentity();
|
|
||||||
|
|
||||||
base.Can_add_and_remove_self_refs();
|
|
||||||
|
|
||||||
AssertSql(
|
|
||||||
"""
|
|
||||||
@p0=NULL (Size = 4000)
|
|
||||||
@p1='1' (Nullable = false) (Size = 4000)
|
|
||||||
@p2=NULL (DbType = Int32)
|
|
||||||
@p3=NULL (DbType = Int32)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
INSERT INTO [Person] ([Country], [Name], [ParentId], [ZipCode])
|
|
||||||
OUTPUT INSERTED.[PersonId]
|
|
||||||
VALUES (@p0, @p1, @p2, @p3);
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p4=NULL (Size = 4000)
|
|
||||||
@p5='2' (Nullable = false) (Size = 4000)
|
|
||||||
@p6='1' (Nullable = true)
|
|
||||||
@p7=NULL (DbType = Int32)
|
|
||||||
@p8=NULL (Size = 4000)
|
|
||||||
@p9='3' (Nullable = false) (Size = 4000)
|
|
||||||
@p10='1' (Nullable = true)
|
|
||||||
@p11=NULL (DbType = Int32)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
MERGE [Person] USING (
|
|
||||||
VALUES (@p4, @p5, @p6, @p7, 0),
|
|
||||||
(@p8, @p9, @p10, @p11, 1)) AS i ([Country], [Name], [ParentId], [ZipCode], _Position) ON 1=0
|
|
||||||
WHEN NOT MATCHED THEN
|
|
||||||
INSERT ([Country], [Name], [ParentId], [ZipCode])
|
|
||||||
VALUES (i.[Country], i.[Name], i.[ParentId], i.[ZipCode])
|
|
||||||
OUTPUT INSERTED.[PersonId], i._Position;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p12=NULL (Size = 4000)
|
|
||||||
@p13='4' (Nullable = false) (Size = 4000)
|
|
||||||
@p14='2' (Nullable = true)
|
|
||||||
@p15=NULL (DbType = Int32)
|
|
||||||
@p16=NULL (Size = 4000)
|
|
||||||
@p17='5' (Nullable = false) (Size = 4000)
|
|
||||||
@p18='2' (Nullable = true)
|
|
||||||
@p19=NULL (DbType = Int32)
|
|
||||||
@p20=NULL (Size = 4000)
|
|
||||||
@p21='6' (Nullable = false) (Size = 4000)
|
|
||||||
@p22='3' (Nullable = true)
|
|
||||||
@p23=NULL (DbType = Int32)
|
|
||||||
@p24=NULL (Size = 4000)
|
|
||||||
@p25='7' (Nullable = false) (Size = 4000)
|
|
||||||
@p26='3' (Nullable = true)
|
|
||||||
@p27=NULL (DbType = Int32)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
MERGE [Person] USING (
|
|
||||||
VALUES (@p12, @p13, @p14, @p15, 0),
|
|
||||||
(@p16, @p17, @p18, @p19, 1),
|
|
||||||
(@p20, @p21, @p22, @p23, 2),
|
|
||||||
(@p24, @p25, @p26, @p27, 3)) AS i ([Country], [Name], [ParentId], [ZipCode], _Position) ON 1=0
|
|
||||||
WHEN NOT MATCHED THEN
|
|
||||||
INSERT ([Country], [Name], [ParentId], [ZipCode])
|
|
||||||
VALUES (i.[Country], i.[Name], i.[ParentId], i.[ZipCode])
|
|
||||||
OUTPUT INSERTED.[PersonId], i._Position;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p0='4'
|
|
||||||
@p1='5'
|
|
||||||
@p2='6'
|
|
||||||
@p3='2'
|
|
||||||
@p4='7'
|
|
||||||
@p5='3'
|
|
||||||
@p6=NULL (Size = 4000)
|
|
||||||
@p7='1' (Nullable = false) (Size = 4000)
|
|
||||||
@p8=NULL (DbType = Int32)
|
|
||||||
@p9=NULL (DbType = Int32)
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p0;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p1;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p2;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p3;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p4;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p5;
|
|
||||||
INSERT INTO [Person] ([Country], [Name], [ParentId], [ZipCode])
|
|
||||||
OUTPUT INSERTED.[PersonId]
|
|
||||||
VALUES (@p6, @p7, @p8, @p9);
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p10='1'
|
|
||||||
@p11=NULL (Size = 4000)
|
|
||||||
@p12='2' (Nullable = false) (Size = 4000)
|
|
||||||
@p13='8' (Nullable = true)
|
|
||||||
@p14=NULL (DbType = Int32)
|
|
||||||
@p15=NULL (Size = 4000)
|
|
||||||
@p16='3' (Nullable = false) (Size = 4000)
|
|
||||||
@p17='8' (Nullable = true)
|
|
||||||
@p18=NULL (DbType = Int32)
|
|
||||||
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
DELETE FROM [Person]
|
|
||||||
OUTPUT 1
|
|
||||||
WHERE [PersonId] = @p10;
|
|
||||||
MERGE [Person] USING (
|
|
||||||
VALUES (@p11, @p12, @p13, @p14, 0),
|
|
||||||
(@p15, @p16, @p17, @p18, 1)) AS i ([Country], [Name], [ParentId], [ZipCode], _Position) ON 1=0
|
|
||||||
WHEN NOT MATCHED THEN
|
|
||||||
INSERT ([Country], [Name], [ParentId], [ZipCode])
|
|
||||||
VALUES (i.[Country], i.[Name], i.[ParentId], i.[ZipCode])
|
|
||||||
OUTPUT INSERTED.[PersonId], i._Position;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
@p19=NULL (Size = 4000)
|
|
||||||
@p20='4' (Nullable = false) (Size = 4000)
|
|
||||||
@p21='9' (Nullable = true)
|
|
||||||
@p22=NULL (DbType = Int32)
|
|
||||||
@p23=NULL (Size = 4000)
|
|
||||||
@p24='5' (Nullable = false) (Size = 4000)
|
|
||||||
@p25='9' (Nullable = true)
|
|
||||||
@p26=NULL (DbType = Int32)
|
|
||||||
@p27=NULL (Size = 4000)
|
|
||||||
@p28='6' (Nullable = false) (Size = 4000)
|
|
||||||
@p29='10' (Nullable = true)
|
|
||||||
@p30=NULL (DbType = Int32)
|
|
||||||
@p31=NULL (Size = 4000)
|
|
||||||
@p32='7' (Nullable = false) (Size = 4000)
|
|
||||||
@p33='10' (Nullable = true)
|
|
||||||
@p34=NULL (DbType = Int32)
|
|
||||||
|
|
||||||
SET IMPLICIT_TRANSACTIONS OFF;
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
MERGE [Person] USING (
|
|
||||||
VALUES (@p19, @p20, @p21, @p22, 0),
|
|
||||||
(@p23, @p24, @p25, @p26, 1),
|
|
||||||
(@p27, @p28, @p29, @p30, 2),
|
|
||||||
(@p31, @p32, @p33, @p34, 3)) AS i ([Country], [Name], [ParentId], [ZipCode], _Position) ON 1=0
|
|
||||||
WHEN NOT MATCHED THEN
|
|
||||||
INSERT ([Country], [Name], [ParentId], [ZipCode])
|
|
||||||
VALUES (i.[Country], i.[Name], i.[ParentId], i.[ZipCode])
|
|
||||||
OUTPUT INSERTED.[PersonId], i._Position;
|
|
||||||
""",
|
|
||||||
//
|
|
||||||
"""
|
|
||||||
SELECT [p].[PersonId], [p].[Country], [p].[Name], [p].[ParentId], [p].[ZipCode], [p].[Address_City], [p].[Country], [p].[ZipCode], [p0].[PersonId], [p0].[Country], [p0].[Name], [p0].[ParentId], [p0].[ZipCode], [p0].[Address_City], [p0].[Country], [p0].[ZipCode], [p1].[PersonId], [p1].[Country], [p1].[Name], [p1].[ParentId], [p1].[ZipCode], [p1].[Address_City], [p1].[Country], [p1].[ZipCode], [p2].[PersonId], [p2].[Country], [p2].[Name], [p2].[ParentId], [p2].[ZipCode], [p2].[Address_City], [p2].[Country], [p2].[ZipCode]
|
|
||||||
FROM [Person] AS [p]
|
|
||||||
LEFT JOIN [Person] AS [p0] ON [p].[ParentId] = [p0].[PersonId]
|
|
||||||
LEFT JOIN [Person] AS [p1] ON [p0].[ParentId] = [p1].[PersonId]
|
|
||||||
LEFT JOIN [Person] AS [p2] ON [p1].[ParentId] = [p2].[PersonId]
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Identifiers_are_generated_correctly()
|
|
||||||
{
|
|
||||||
using var context = CreateContext();
|
|
||||||
var entityType = context.Model.FindEntityType(
|
|
||||||
typeof(
|
|
||||||
LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkingCorrectly
|
|
||||||
))!;
|
|
||||||
Assert.Equal(
|
|
||||||
"LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorking~",
|
|
||||||
entityType.GetTableName());
|
|
||||||
Assert.Equal(
|
|
||||||
"PK_LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWork~",
|
|
||||||
entityType.GetKeys().Single().GetName());
|
|
||||||
Assert.Equal(
|
|
||||||
"FK_LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWork~",
|
|
||||||
entityType.GetForeignKeys().Single().GetConstraintName());
|
|
||||||
Assert.Equal(
|
|
||||||
"IX_LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWork~",
|
|
||||||
entityType.GetIndexes().Single().GetDatabaseName());
|
|
||||||
|
|
||||||
var entityType2 = context.Model.FindEntityType(
|
|
||||||
typeof(
|
|
||||||
LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkingCorrectlyDetails
|
|
||||||
))!;
|
|
||||||
|
|
||||||
Assert.Equal(
|
|
||||||
"LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkin~1",
|
|
||||||
entityType2.GetTableName());
|
|
||||||
Assert.Equal(
|
|
||||||
"PK_LoginDetails",
|
|
||||||
entityType2.GetKeys().Single().GetName());
|
|
||||||
Assert.Equal(
|
|
||||||
"ExtraPropertyWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkingCo~",
|
|
||||||
entityType2.GetProperties().ElementAt(1).GetColumnName(StoreObjectIdentifier.Table(entityType2.GetTableName()!)));
|
|
||||||
Assert.Equal(
|
|
||||||
"ExtraPropertyWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWorkingC~1",
|
|
||||||
entityType2.GetProperties().ElementAt(2).GetColumnName(StoreObjectIdentifier.Table(entityType2.GetTableName()!)));
|
|
||||||
Assert.Equal(
|
|
||||||
"IX_LoginEntityTypeWithAnExtremelyLongAndOverlyConvolutedNameThatIsUsedToVerifyThatTheStoreIdentifierGenerationLengthLimitIsWork~",
|
|
||||||
entityType2.GetIndexes().Single().GetDatabaseName());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void AssertSql(params string[] expected)
|
|
||||||
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
|
|
||||||
|
|
||||||
protected void AssertContainsSql(params string[] expected)
|
|
||||||
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected, assertOrder: false);
|
|
||||||
|
|
||||||
public abstract class UpdatesJetFixtureBase : UpdatesRelationalFixture
|
|
||||||
{
|
|
||||||
protected override ITestStoreFactory TestStoreFactory
|
|
||||||
=> JetTestStoreFactory.Instance;
|
|
||||||
|
|
||||||
public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder)
|
|
||||||
=> base.AddOptions(builder).ConfigureWarnings(
|
|
||||||
w =>
|
|
||||||
{
|
|
||||||
w.Log(JetEventId.DecimalTypeKeyWarning);
|
|
||||||
});
|
|
||||||
|
|
||||||
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
|
|
||||||
=> configurationBuilder.Properties<decimal>().HaveColumnType("decimal(18, 2)");
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder, context);
|
|
||||||
|
|
||||||
modelBuilder.Entity<ProductBase>()
|
|
||||||
.Property(p => p.Id).HasDefaultValueSql("GenGUID()");
|
|
||||||
|
|
||||||
modelBuilder.Entity<Product>().HasIndex(p => new { p.Name, p.Price }).HasFilter("Name IS NOT NULL");
|
|
||||||
}
|
|
||||||
public virtual void ResetIdentity()
|
|
||||||
{
|
|
||||||
var context = CreateContext();
|
|
||||||
context.Database.ExecuteSqlRaw(ResetIdentitySql);
|
|
||||||
TestSqlLoggerFactory.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private const string ResetIdentitySql = @"
|
|
||||||
-- We can't use TRUNCATE on tables with foreign keys, so we DELETE and reset IDENTITY manually.
|
|
||||||
-- DBCC CHECKIDENT resets IDENTITY, but behaves differently based on whether whether rows were ever inserted (seed+1) or not (seed).
|
|
||||||
-- So we insert a dummy row before deleting everything to make sure we get the seed value 1.
|
|
||||||
INSERT INTO [Person] ([Name]) VALUES ('');
|
|
||||||
DELETE FROM [Person];
|
|
||||||
DBCC CHECKIDENT ('[Person]', RESEED, 0);";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue