Skip to content

Commit

Permalink
Add change tracking and query support for collections of owned types.
Browse files Browse the repository at this point in the history
Improve detection of the inverse navigation for owned types.

Fixes #8172
  • Loading branch information
AndriySvyryd committed Jul 11, 2018
1 parent c3eef6b commit 3014fa3
Show file tree
Hide file tree
Showing 25 changed files with 550 additions and 602 deletions.
1 change: 1 addition & 0 deletions EFCore.Runtime.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=Microsoft_002EEntityFrameworkCore_002EAnnotations/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EF/@EntryIndexedValue">EF</s:String>
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=D44E9AA0167CE64B866A64486B319AB0/RelativePath/@EntryValue">..\EFCore.sln.DotSettings</s:String>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=D44E9AA0167CE64B866A64486B319AB0/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileD44E9AA0167CE64B866A64486B319AB0/@KeyIndexDefined">True</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.TestModels.ComplexNavigationsModel;
Expand Down Expand Up @@ -33,18 +34,23 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
.Ignore(e => e.OneToMany_Required_Self)
.Ignore(e => e.OneToMany_Required_Self_Inverse)
.Ignore(e => e.OneToMany_Optional_Self)
.Ignore(e => e.OneToMany_Optional_Self_Inverse)
.Ignore(e => e.OneToMany_Required)
.Ignore(e => e.OneToMany_Optional);
.Ignore(e => e.OneToMany_Optional_Self_Inverse);

var level1 = level1Builder.Metadata;

ForeignKey level2Fk;
var level2 = level1.Model.AddEntityType(typeof(Level2), nameof(Level1.OneToOne_Required_PK), level1);
var level2Fk = level2.AddForeignKey(level2.FindProperty(nameof(Level2.Id)), level1.FindPrimaryKey(), level1);
level2Fk.HasPrincipalToDependent(nameof(Level1.OneToOne_Required_PK));
level2Fk.IsUnique = true;
level2Fk.DeleteBehavior = DeleteBehavior.Restrict;
using (var batch = ((Model)modelBuilder.Model).ConventionDispatcher.StartBatch())
{
level2Fk = (ForeignKey)level2.AddForeignKey(level2.FindProperty(nameof(Level2.Id)), level1.FindPrimaryKey(), level1);
level2Fk.HasPrincipalToDependent(nameof(Level1.OneToOne_Required_PK));
level2Fk.HasDependentToPrincipal(nameof(Level2.OneToOne_Required_PK_Inverse));
level2Fk.IsUnique = true;
level2Fk.DeleteBehavior = DeleteBehavior.Restrict;
level2Fk = batch.Run(level2Fk);
}

Configure(new ReferenceOwnershipBuilder<Level1, Level2>((EntityType)level1, (EntityType)level2, ((ForeignKey)level2Fk).Builder));
Configure(new ReferenceOwnershipBuilder<Level1, Level2>((EntityType)level1, level2Fk.DeclaringEntityType, level2Fk.Builder));

modelBuilder.Entity<InheritanceBase1>().Property(e => e.Id).ValueGeneratedNever();
modelBuilder.Entity<InheritanceBase2>().Property(e => e.Id).ValueGeneratedNever();
Expand Down Expand Up @@ -89,10 +95,7 @@ protected virtual void Configure(ReferenceOwnershipBuilder<Level1, Level2> l2)
.Ignore(e => e.OneToMany_Required_Self_Inverse)
.Ignore(e => e.OneToMany_Optional_Self)
.Ignore(e => e.OneToMany_Optional_Self_Inverse)
.Ignore(e => e.OneToMany_Required)
.Ignore(e => e.OneToMany_Required_Inverse)
.Ignore(e => e.OneToMany_Optional)
.Ignore(e => e.OneToMany_Optional_Inverse).OwnedEntityType;
.OwnedEntityType;

l2.Property(e => e.Id).ValueGeneratedNever();

Expand All @@ -112,13 +115,28 @@ protected virtual void Configure(ReferenceOwnershipBuilder<Level1, Level2> l2)
.HasForeignKey<Level2>(e => e.Level1_Optional_Id)
.IsRequired(false);

l2.HasOne(e => e.OneToMany_Required_Inverse)
.WithMany(e => e.OneToMany_Required)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);

l2.HasOne(e => e.OneToMany_Optional_Inverse)
.WithMany(e => e.OneToMany_Optional)
.IsRequired(false);

ForeignKey level3Fk;
var level3 = level2.Model.AddEntityType(typeof(Level3), nameof(Level2.OneToOne_Required_PK), level2);
var level3Fk = level3.AddForeignKey(level3.FindProperty(nameof(Level3.Id)), level2.FindPrimaryKey(), level2);
level3Fk.HasPrincipalToDependent(nameof(Level2.OneToOne_Required_PK));
level3Fk.IsUnique = true;
level3Fk.DeleteBehavior = DeleteBehavior.Restrict;
using (var batch = ((Model)level2.Model).ConventionDispatcher.StartBatch())
{
level3Fk = (ForeignKey)level3.AddForeignKey(level3.FindProperty(nameof(Level3.Id)), level2.FindPrimaryKey(), level2);
level3Fk.HasPrincipalToDependent(nameof(Level2.OneToOne_Required_PK));
level3Fk.HasDependentToPrincipal(nameof(Level3.OneToOne_Required_PK_Inverse));
level3Fk.IsUnique = true;
level3Fk.DeleteBehavior = DeleteBehavior.Restrict;
level3Fk = batch.Run(level3Fk);
}

Configure(new ReferenceOwnershipBuilder<Level2, Level3>((EntityType)level2, (EntityType)level3, ((ForeignKey)level3Fk).Builder));
Configure(new ReferenceOwnershipBuilder<Level2, Level3>((EntityType)level2, level3Fk.DeclaringEntityType, level3Fk.Builder));
}

protected virtual void Configure(ReferenceOwnershipBuilder<Level2, Level3> l3)
Expand All @@ -128,10 +146,7 @@ protected virtual void Configure(ReferenceOwnershipBuilder<Level2, Level3> l3)
.Ignore(e => e.OneToMany_Required_Self_Inverse)
.Ignore(e => e.OneToMany_Optional_Self)
.Ignore(e => e.OneToMany_Optional_Self_Inverse)
.Ignore(e => e.OneToMany_Required)
.Ignore(e => e.OneToMany_Required_Inverse)
.Ignore(e => e.OneToMany_Optional)
.Ignore(e => e.OneToMany_Optional_Inverse).OwnedEntityType;
.OwnedEntityType;

l3.Property(e => e.Id).ValueGeneratedNever();

Expand All @@ -151,13 +166,28 @@ protected virtual void Configure(ReferenceOwnershipBuilder<Level2, Level3> l3)
.HasForeignKey<Level3>(e => e.Level2_Optional_Id)
.IsRequired(false);

l3.HasOne(e => e.OneToMany_Required_Inverse)
.WithMany(e => e.OneToMany_Required)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);

l3.HasOne(e => e.OneToMany_Optional_Inverse)
.WithMany(e => e.OneToMany_Optional)
.IsRequired(false);

ForeignKey level4Fk;
var level4 = level3.Model.AddEntityType(typeof(Level4), nameof(Level3.OneToOne_Required_PK), level3);
var level4Fk = level4.AddForeignKey(level4.FindProperty(nameof(Level4.Id)), level3.FindPrimaryKey(), level3);
level4Fk.HasPrincipalToDependent(nameof(Level3.OneToOne_Required_PK));
level4Fk.IsUnique = true;
level4Fk.DeleteBehavior = DeleteBehavior.Restrict;
using (var batch = ((Model)level3.Model).ConventionDispatcher.StartBatch())
{
level4Fk = (ForeignKey)level4.AddForeignKey(level4.FindProperty(nameof(Level4.Id)), level3.FindPrimaryKey(), level3);
level4Fk.HasPrincipalToDependent(nameof(Level3.OneToOne_Required_PK));
level4Fk.HasDependentToPrincipal(nameof(Level4.OneToOne_Required_PK_Inverse));
level4Fk.IsUnique = true;
level4Fk.DeleteBehavior = DeleteBehavior.Restrict;
level4Fk = batch.Run(level4Fk);
}

Configure(new ReferenceOwnershipBuilder<Level3, Level4>((EntityType)level3, (EntityType)level4, ((ForeignKey)level4Fk).Builder));
Configure(new ReferenceOwnershipBuilder<Level3, Level4>((EntityType)level3, level4Fk.DeclaringEntityType, level4Fk.Builder));
}

protected virtual void Configure(ReferenceOwnershipBuilder<Level3, Level4> l4)
Expand All @@ -166,9 +196,7 @@ protected virtual void Configure(ReferenceOwnershipBuilder<Level3, Level4> l4)
.Ignore(e => e.OneToMany_Required_Self)
.Ignore(e => e.OneToMany_Required_Self_Inverse)
.Ignore(e => e.OneToMany_Optional_Self)
.Ignore(e => e.OneToMany_Optional_Self_Inverse)
.Ignore(e => e.OneToMany_Required_Inverse)
.Ignore(e => e.OneToMany_Optional_Inverse);
.Ignore(e => e.OneToMany_Optional_Self_Inverse);

l4.Property(e => e.Id).ValueGeneratedNever();

Expand All @@ -187,6 +215,15 @@ protected virtual void Configure(ReferenceOwnershipBuilder<Level3, Level4> l4)
.WithOne(e => e.OneToOne_Optional_FK)
.HasForeignKey<Level4>(e => e.Level3_Optional_Id)
.IsRequired(false);

l4.HasOne(e => e.OneToMany_Required_Inverse)
.WithMany(e => e.OneToMany_Required)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);

l4.HasOne(e => e.OneToMany_Optional_Inverse)
.WithMany(e => e.OneToMany_Optional)
.IsRequired(false);
}

protected override void Seed(ComplexNavigationsContext context)
Expand Down
Loading

0 comments on commit 3014fa3

Please sign in to comment.