// 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.ChangeTracking; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using System.Threading.Tasks; namespace EntityFrameworkCore.Jet.FunctionalTests; #nullable disable public class GraphUpdatesJetOwnedTest(GraphUpdatesJetOwnedTest.JetFixture fixture) : GraphUpdatesJetTestBase(fixture) { // No owned types public override Task Update_root_by_collection_replacement_of_inserted_first_level(bool async) => Task.CompletedTask; // No owned types public override Task Mark_explicitly_set_dependent_appropriately_with_any_inheritance_and_stable_generator(bool async, bool useAdd) => Task.CompletedTask; // No owned types public override Task Mark_explicitly_set_stable_dependent_appropriately(bool async, bool useAdd) => Task.CompletedTask; // No owned types public override Task Mark_explicitly_set_stable_dependent_appropriately_when_deep_in_graph(bool async, bool useAdd) => Task.CompletedTask; // No owned types public override Task Update_root_by_collection_replacement_of_deleted_first_level(bool async) => Task.CompletedTask; // No owned types public override Task Update_root_by_collection_replacement_of_inserted_second_level(bool async) => Task.CompletedTask; // No owned types public override Task Update_root_by_collection_replacement_of_deleted_second_level(bool async) => Task.CompletedTask; // No owned types public override Task Update_root_by_collection_replacement_of_inserted_first_level_level(bool async) => Task.CompletedTask; // No owned types public override Task Update_root_by_collection_replacement_of_deleted_third_level(bool async) => Task.CompletedTask; // No owned types public override Task Sever_relationship_that_will_later_be_deleted(bool async) => Task.CompletedTask; // No owned types public override Task Alternate_key_over_foreign_key_doesnt_bypass_delete_behavior(bool async) => Task.CompletedTask; // No owned types public override Task Shadow_skip_navigation_in_base_class_is_handled(bool async) => Task.CompletedTask; // Owned dependents are always loaded public override Task Required_one_to_one_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) => Task.CompletedTask; public override Task Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) => Task.CompletedTask; // No owned types public override Task Can_insert_when_composite_FK_has_default_value_for_one_part(bool async) => Task.CompletedTask; public override Task Required_one_to_one_relationships_are_one_to_one(CascadeTiming? deleteOrphansTiming) => Task.CompletedTask; public override Task Required_one_to_one_with_AK_relationships_are_one_to_one(CascadeTiming? deleteOrphansTiming) => Task.CompletedTask; // No owned types public override Task Can_insert_when_bool_PK_in_composite_key_has_sentinel_value(bool async, bool initialValue) => Task.CompletedTask; // No owned types public override Task Can_insert_when_int_PK_in_composite_key_has_sentinel_value(bool async, int initialValue) => Task.CompletedTask; // No owned types public override Task Can_insert_when_nullable_bool_PK_in_composite_key_has_sentinel_value(bool async, bool? initialValue) => Task.CompletedTask; // No owned types public override Task Throws_for_single_property_bool_key_with_default_value_generation(bool async, bool initialValue) => Task.CompletedTask; // No owned types public override Task Throws_for_single_property_nullable_bool_key_with_default_value_generation(bool async, bool? initialValue) => Task.CompletedTask; protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) => facade.UseTransaction(transaction.GetDbTransaction()); public class JetFixture : GraphUpdatesJetFixtureBase { protected override string StoreName => "GraphOwnedUpdatesTest"; protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { modelBuilder.Entity( b => { b.OwnsOne(e => e.OptionalSingle).OwnsOne(e => e.Single); b.OwnsOne(e => e.RequiredSingle).OwnsOne(e => e.Single); b.OwnsMany(e => e.OptionalChildren).OwnsMany(e => e.Children); b.OwnsMany(e => e.RequiredChildren).OwnsMany(e => e.Children); }); modelBuilder.Entity( b => { b.Property(e => e.AlternateId).ValueGeneratedOnAdd(); // TODO: Owned inheritance support #9630 b.HasMany(e => e.RequiredChildren) .WithOne(e => e.Parent) .HasForeignKey(e => e.ParentId); modelBuilder.Entity() .HasMany(e => e.Children) .WithOne(e => e.Parent) .HasForeignKey(e => e.ParentId); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); b.HasMany(e => e.OptionalChildren) .WithOne(e => e.Parent) .HasForeignKey(e => e.ParentId) .OnDelete(DeleteBehavior.SetNull); b.OwnsOne( e => e.RequiredSingle, r => { r.WithOwner(e => e.Root) .HasForeignKey(e => e.Id); r.OwnsOne(e => e.Single) .WithOwner(e => e.Back) .HasForeignKey(e => e.Id); }); b.HasOne(e => e.OptionalSingle) .WithOne(e => e.Root) .HasForeignKey(e => e.RootId) .OnDelete(DeleteBehavior.SetNull); b.HasOne(e => e.OptionalSingleDerived) .WithOne(e => e.DerivedRoot) .HasForeignKey(e => e.DerivedRootId) .OnDelete(DeleteBehavior.ClientSetNull); b.HasOne(e => e.OptionalSingleMoreDerived) .WithOne(e => e.MoreDerivedRoot) .HasForeignKey(e => e.MoreDerivedRootId) .OnDelete(DeleteBehavior.ClientSetNull); // TODO: Owned inheritance support #9630 b.HasOne(e => e.RequiredNonPkSingle) .WithOne(e => e.Root) .HasForeignKey(e => e.RootId); b.HasOne(e => e.RequiredNonPkSingleDerived) .WithOne(e => e.DerivedRoot) .HasForeignKey(e => e.DerivedRootId) .OnDelete(DeleteBehavior.Restrict); b.HasOne(e => e.RequiredNonPkSingleMoreDerived) .WithOne(e => e.MoreDerivedRoot) .HasForeignKey(e => e.MoreDerivedRootId) .OnDelete(DeleteBehavior.Restrict); // TODO: Owned inheritance support #9630 b.HasMany(e => e.RequiredChildrenAk) .WithOne(e => e.Parent) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.ParentId); modelBuilder.Entity( b => { b.Property(e => e.AlternateId) .ValueGeneratedOnAdd(); b.HasMany(e => e.Children) .WithOne(e => e.Parent) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.ParentId); b.HasMany(e => e.CompositeChildren) .WithOne(e => e.Parent) .HasPrincipalKey( e => new { e.Id, e.AlternateId }) .HasForeignKey( e => new { e.ParentId, e.ParentAlternateId }); }); modelBuilder.Entity() .Property(e => e.AlternateId) .ValueGeneratedOnAdd(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); b.HasMany(e => e.OptionalChildrenAk) .WithOne(e => e.Parent) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.ParentId) .OnDelete(DeleteBehavior.SetNull); b.OwnsOne( e => e.RequiredSingleAk, r => { r.WithOwner(e => e.Root) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.RootId); r.HasKey(e => e.Id); r.Property(e => e.AlternateId) .ValueGeneratedOnAdd(); r.OwnsOne( e => e.Single, r2 => { r2.WithOwner(e => e.Back) .HasForeignKey(e => e.BackId) .HasPrincipalKey(e => e.AlternateId); r2.HasKey(e => e.Id); r2.Property(e => e.Id) .ValueGeneratedOnAdd(); r2.Property(e => e.AlternateId) .ValueGeneratedOnAdd(); r2.ToTable("RequiredSingleAk2"); }); r.OwnsOne( e => e.SingleComposite, r2 => { r2.WithOwner(e => e.Back) .HasForeignKey(e => new { e.BackId, e.BackAlternateId }) .HasPrincipalKey(e => new { e.Id, e.AlternateId }); r2.HasKey(e => e.Id); r2.ToTable("RequiredSingleComposite2"); }); // Table splitting using AK is not supported #23208 r.ToTable("RequiredSingleAk1"); }); b.HasOne(e => e.OptionalSingleAk) .WithOne(e => e.Root) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.RootId) .OnDelete(DeleteBehavior.SetNull); b.HasOne(e => e.OptionalSingleAkDerived) .WithOne(e => e.DerivedRoot) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.DerivedRootId) .OnDelete(DeleteBehavior.ClientSetNull); b.HasOne(e => e.OptionalSingleAkMoreDerived) .WithOne(e => e.MoreDerivedRoot) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.MoreDerivedRootId) .OnDelete(DeleteBehavior.ClientSetNull); b.HasOne(e => e.RequiredNonPkSingleAk) .WithOne(e => e.Root) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.RootId); b.HasOne(e => e.RequiredNonPkSingleAkDerived) .WithOne(e => e.DerivedRoot) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.DerivedRootId) .OnDelete(DeleteBehavior.Restrict); b.HasOne(e => e.RequiredNonPkSingleAkMoreDerived) .WithOne(e => e.MoreDerivedRoot) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.MoreDerivedRootId) .OnDelete(DeleteBehavior.Restrict); b.HasMany(e => e.RequiredCompositeChildren) .WithOne(e => e.Parent) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.ParentAlternateId); }); modelBuilder.Entity( b => { b.HasMany(e => e.Children) .WithOne(e => e.Parent) .HasForeignKey(e => e.ParentId) .OnDelete(DeleteBehavior.SetNull); b.HasMany(e => e.CompositeChildren) .WithOne(e => e.Parent2) .HasForeignKey(e => new { e.Parent2Id }); }); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity() .HasOne(e => e.Single) .WithOne(e => e.Back) .HasForeignKey(e => e.BackId) .OnDelete(DeleteBehavior.SetNull); modelBuilder.Entity( b => { b.HasDiscriminator(e => e.Disc) .HasValue(new MyDiscriminator(1)) .HasValue(new MyDiscriminator(2)) .HasValue(new MyDiscriminator(3)); b.Property(e => e.Disc) .HasConversion( v => v.Value, v => new MyDiscriminator(v), new ValueComparer( (l, r) => l.Value == r.Value, v => v.Value.GetHashCode(), v => new MyDiscriminator(v.Value))) .Metadata .SetAfterSaveBehavior(PropertySaveBehavior.Save); }); modelBuilder.Entity() .HasOne(e => e.Single) .WithOne(e => e.Back) .HasForeignKey(e => e.BackId); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity( b => { b.Property(e => e.AlternateId) .ValueGeneratedOnAdd(); b.HasOne(e => e.Single) .WithOne(e => e.Back) .HasForeignKey(e => e.BackId) .HasPrincipalKey(e => e.AlternateId); }); modelBuilder.Entity( b => { b.Property(e => e.AlternateId) .ValueGeneratedOnAdd(); b.HasMany(e => e.Children) .WithOne(e => e.Parent) .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.ParentId) .OnDelete(DeleteBehavior.SetNull); b.HasMany(e => e.CompositeChildren) .WithOne(e => e.Parent) .HasPrincipalKey( e => new { e.Id, e.AlternateId }) .HasForeignKey( e => new { e.ParentId, e.ParentAlternateId }); }); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity() .Property(e => e.AlternateId) .ValueGeneratedOnAdd(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity() .Property(e => e.AlternateId) .ValueGeneratedOnAdd(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity( b => { b.Property(e => e.AlternateId) .ValueGeneratedOnAdd(); b.HasOne(e => e.Single) .WithOne(e => e.Back) .HasForeignKey(e => e.BackId) .HasPrincipalKey(e => e.AlternateId) .OnDelete(DeleteBehavior.SetNull); b.HasOne(e => e.SingleComposite) .WithOne(e => e.Back) .HasForeignKey( e => new { e.BackId, e.ParentAlternateId }) .HasPrincipalKey( e => new { e.Id, e.AlternateId }); }); modelBuilder.Entity() .Property(e => e.AlternateId) .ValueGeneratedOnAdd(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity( eb => { eb.Property(e => e.Id).ValueGeneratedNever(); eb.HasKey( e => new { e.Id, e.ParentAlternateId }); eb.HasMany(e => e.CompositeChildren) .WithOne(e => e.Parent) .HasPrincipalKey( e => new { e.Id, e.ParentAlternateId }) .HasForeignKey( e => new { e.ParentId, e.ParentAlternateId }); }); modelBuilder.Entity( eb => { eb.Property(e => e.Id).ValueGeneratedNever(); eb.HasKey( e => new { e.Id, e.ParentAlternateId }); eb.HasOne(e => e.Root) .WithMany() .HasPrincipalKey(e => e.AlternateId) .HasForeignKey(e => e.ParentAlternateId); }); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity() .HasMany(qt => qt.Choices) .WithOne() .HasForeignKey(tc => tc.QuestTaskId); modelBuilder.Entity() .HasMany(hat => hat.Choices) .WithOne() .HasForeignKey(tc => tc.QuestTaskId); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity() .HasIndex(e => e.BarCode) .IsUnique(); modelBuilder.Entity( builder => { builder.HasMany(x => x.Dependants).WithOne(x => x.Root) .HasForeignKey(x => new { x.RootId }) .HasPrincipalKey(x => x.Id) .OnDelete(DeleteBehavior.Cascade); builder.HasMany(x => x.Parents).WithOne(x => x.Root) .HasForeignKey(x => new { x.RootId }) .HasPrincipalKey(x => x.Id) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity( builder => { builder.HasOne(x => x.Dependant).WithOne(x => x!.Parent).IsRequired(false) .HasForeignKey(x => new { x.RootId, x.DependantId }) .HasPrincipalKey(x => new { x.RootId, x.Id }) .OnDelete(DeleteBehavior.ClientSetNull); }); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity( b => { b.Navigation(e => e.Owned).IsRequired(); b.Navigation(e => e.OwnedWithKey).IsRequired(); b.OwnsMany( e => e.OwnedCollectionPrivateKey, b => b.HasKey("OwnerWithKeyedCollectionId", "PrivateKey")); }); modelBuilder .Entity() .OwnsMany(e => e.Owned, owned => owned.HasKey("Id")); modelBuilder.Entity( b => { b.Property(e => e.Id).ValueGeneratedNever(); b.OwnsOne( e => e.Owned, b => b.Property("OwnerNoKeyGenerationId").ValueGeneratedNever()); b.OwnsMany( e => e.OwnedCollection, b => { b.Property("OwnedNoKeyGenerationId").ValueGeneratedNever(); b.Property("OwnerNoKeyGenerationId").ValueGeneratedNever(); }); }); modelBuilder.Entity().HasData( new Provider { Id = "prov1" }, new Provider { Id = "prov2" }); modelBuilder.Entity().HasData( new Partner { Id = "partner1" }); modelBuilder.Entity( b => { b.HasOne(p => p.Partner).WithMany().IsRequired().HasForeignKey("PartnerId"); b.HasOne().WithMany().IsRequired().HasForeignKey("ProviderId"); b.HasDiscriminator("ProviderId") .HasValue("prov1") .HasValue("prov2"); }); modelBuilder.Entity( b => { b.Property("EntityZId"); b.HasOne(e => e.EntityZ).WithMany().HasForeignKey("EntityZId").IsRequired(); }); modelBuilder.Entity(); modelBuilder.Entity( b => { b.Property(e => e.AccessStateId).ValueGeneratedNever(); b.HasData(new AccessState { AccessStateId = 1 }); }); modelBuilder.Entity( b => { b.Property(e => e.IdUserState).HasDefaultValue(1); b.HasOne(e => e.UserState).WithMany(e => e.Users).HasForeignKey(e => e.IdUserState); }); modelBuilder.Entity( b => { b.Property(e => e.AccessStateWithSentinelId).ValueGeneratedNever(); b.HasData(new AccessStateWithSentinel { AccessStateWithSentinelId = 1 }); }); modelBuilder.Entity( b => { b.Property(e => e.IdUserState).HasDefaultValue(1).HasSentinel(667); b.HasOne(e => e.UserState).WithMany(e => e.Users).HasForeignKey(e => e.IdUserState); }); modelBuilder.Entity( b => { b.HasAlternateKey(e => e.AlternateId); b.OwnsOne( x => x.Child, b => { b.WithOwner(e => e.Parent).HasForeignKey(e => e.ParentId); }); }); modelBuilder.Entity().Property(x => x.Id).HasColumnType("int"); modelBuilder.Entity().Property(x => x.Id).HasColumnType("int"); modelBuilder.Entity().Property(x => x.Id).HasColumnType("int"); } } }