Skip to content

Commit

Permalink
Make ITableBase methods throw for entity types not mapped to the table
Browse files Browse the repository at this point in the history
Fixes #22020
  • Loading branch information
AndriySvyryd committed Aug 14, 2020
1 parent ce45f9b commit ca2e07a
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 27 deletions.
14 changes: 6 additions & 8 deletions src/EFCore.Relational/Metadata/Internal/RelationalModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,15 +1036,13 @@ private static void PopulateRowInternalForeignKeys(TableBase table)
}
optionalTypes[entityType] = optional;

if (!referencingInternalForeignKeyMap.TryGetValue(entityType, out var referencingInternalForeignKeys))
if (referencingInternalForeignKeyMap.TryGetValue(entityType, out var referencingInternalForeignKeys))
{
continue;
}

foreach (var referencingForeignKey in referencingInternalForeignKeys)
{
entityTypesToVisit.Enqueue(
(referencingForeignKey.DeclaringEntityType, optional || !referencingForeignKey.IsRequiredDependent));
foreach (var referencingForeignKey in referencingInternalForeignKeys)
{
entityTypesToVisit.Enqueue(
(referencingForeignKey.DeclaringEntityType, optional || !referencingForeignKey.IsRequiredDependent));
}
}

if (table.EntityTypeMappings.Single(etm => etm.EntityType == entityType).IncludesDerivedTypes)
Expand Down
22 changes: 17 additions & 5 deletions src/EFCore.Relational/Metadata/Internal/TableBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace Microsoft.EntityFrameworkCore.Metadata.Internal
Expand Down Expand Up @@ -103,9 +104,16 @@ public virtual IColumnBase FindColumn(IProperty property)

/// <inheritdoc/>
public virtual bool IsOptional(IEntityType entityType)
=> OptionalEntityTypes != null
&& OptionalEntityTypes.TryGetValue(entityType, out var optional)
&& optional;
=> OptionalEntityTypes == null
? GetMappedEntityType(entityType) == null
: !OptionalEntityTypes.TryGetValue(entityType, out var optional)
? throw new InvalidOperationException(RelationalStrings.TableNotMappedEntityType(entityType.DisplayName(), Name))
: optional;

private IEntityType GetMappedEntityType(IEntityType entityType)
=> EntityTypeMappings.Any(m => m.EntityType == entityType)
? entityType
: throw new InvalidOperationException(RelationalStrings.TableNotMappedEntityType(entityType.DisplayName(), Name));

/// <inheritdoc/>
IRelationalModel ITableBase.Model => Model;
Expand All @@ -121,13 +129,17 @@ IEnumerable<IForeignKey> ITableBase.GetRowInternalForeignKeys(IEntityType entity
=> RowInternalForeignKeys != null
&& RowInternalForeignKeys.TryGetValue(entityType, out var foreignKeys)
? foreignKeys
: Enumerable.Empty<IForeignKey>();
: (GetMappedEntityType(entityType) == null)
? null
: Enumerable.Empty<IForeignKey>();

/// <inheritdoc/>
IEnumerable<IForeignKey> ITableBase.GetReferencingRowInternalForeignKeys(IEntityType entityType)
=> ReferencingRowInternalForeignKeys != null
&& ReferencingRowInternalForeignKeys.TryGetValue(entityType, out var foreignKeys)
? foreignKeys
: Enumerable.Empty<IForeignKey>();
: (GetMappedEntityType(entityType) == null)
? null
: Enumerable.Empty<IForeignKey>();
}
}
29 changes: 16 additions & 13 deletions src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -774,25 +774,28 @@ private static IEnumerable<IProperty> GetSortedProperties(IEntityType entityType
groups.Add(group.Key, group.Value.Values.ToList());
}

foreach (var linkingForeignKey in table.GetReferencingRowInternalForeignKeys(entityType))
if (table.EntityTypeMappings.Any(m => m.EntityType == entityType))
{
var linkingNavigationProperty = linkingForeignKey.PrincipalToDependent?.PropertyInfo;
var properties = GetSortedProperties(linkingForeignKey.DeclaringEntityType, table).ToList();
if (linkingNavigationProperty == null)
foreach (var linkingForeignKey in table.GetReferencingRowInternalForeignKeys(entityType))
{
leastPriorityProperties.AddRange(properties);
var linkingNavigationProperty = linkingForeignKey.PrincipalToDependent?.PropertyInfo;
var properties = GetSortedProperties(linkingForeignKey.DeclaringEntityType, table).ToList();
if (linkingNavigationProperty == null)
{
leastPriorityProperties.AddRange(properties);

continue;
}
continue;
}

groups.Add(linkingNavigationProperty, properties);
groups.Add(linkingNavigationProperty, properties);

var clrType = linkingNavigationProperty.DeclaringType;
var index = clrType.GetTypeInfo().DeclaredProperties
.IndexOf(linkingNavigationProperty, PropertyInfoEqualityComparer.Instance);
var clrType = linkingNavigationProperty.DeclaringType;
var index = clrType.GetTypeInfo().DeclaredProperties
.IndexOf(linkingNavigationProperty, PropertyInfoEqualityComparer.Instance);

Check.DebugAssert(clrType != null, "clrType is null");
types.GetOrAddNew(clrType)[index] = linkingNavigationProperty;
Check.DebugAssert(clrType != null, "clrType is null");
types.GetOrAddNew(clrType)[index] = linkingNavigationProperty;
}
}

var graph = new Multigraph<Type, object>();
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/EFCore.Relational/Properties/RelationalStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -744,4 +744,7 @@
<data name="DuplicateKeyTableMismatch" xml:space="preserve">
<value>The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{keyName}' but with different columns ('{table1}' and '{table2}').</value>
</data>
<data name="TableNotMappedEntityType" xml:space="preserve">
<value>The entity type '{entityType}' is not mapped to the store object '{table}'.</value>
</data>
</root>
12 changes: 11 additions & 1 deletion test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.TestUtilities;
Expand Down Expand Up @@ -345,12 +346,22 @@ private static void AssertTables(IRelationalModel model, Mapping mapping)
Assert.Equal(orderCustomerFk, orderCustomerFkConstraint.MappedForeignKeys.Single());
Assert.Equal(new[] { orderDateFkConstraint, orderCustomerFkConstraint }, ordersTable.ForeignKeyConstraints);

var specialCustomerType = model.Model.FindEntityType(typeof(SpecialCustomer));
var orderDetailsOwnership = orderType.FindNavigation(nameof(Order.Details)).ForeignKey;
var orderDetailsType = orderDetailsOwnership.DeclaringEntityType;
Assert.Same(ordersTable, orderDetailsType.GetTableMappings().Single().Table);
Assert.Equal(ordersTable.GetReferencingRowInternalForeignKeys(orderType), ordersTable.GetRowInternalForeignKeys(orderDetailsType));
Assert.Equal(RelationalStrings.TableNotMappedEntityType(nameof(SpecialCustomer), ordersTable.Name),
Assert.Throws<InvalidOperationException>(() =>
ordersTable.GetReferencingRowInternalForeignKeys(specialCustomerType)).Message);
Assert.Equal(RelationalStrings.TableNotMappedEntityType(nameof(SpecialCustomer), ordersTable.Name),
Assert.Throws<InvalidOperationException>(() =>
ordersTable.GetRowInternalForeignKeys(specialCustomerType)).Message);
Assert.False(ordersTable.IsOptional(orderType));
Assert.True(ordersTable.IsOptional(orderDetailsType));
Assert.Equal(RelationalStrings.TableNotMappedEntityType(nameof(SpecialCustomer), ordersTable.Name),
Assert.Throws<InvalidOperationException>(() =>
ordersTable.IsOptional(specialCustomerType)).Message);
Assert.Empty(orderDetailsOwnership.GetMappedConstraints());
Assert.Equal(2, orderDetailsType.GetForeignKeys().Count());

Expand Down Expand Up @@ -391,7 +402,6 @@ private static void AssertTables(IRelationalModel model, Mapping mapping)
var customerTable = customerType.GetTableMappings().Single().Table;
Assert.Equal("Customer", customerTable.Name);

var specialCustomerType = model.Model.FindEntityType(typeof(SpecialCustomer));
var customerPk = specialCustomerType.FindPrimaryKey();

if (mapping == Mapping.TPT)
Expand Down

0 comments on commit ca2e07a

Please sign in to comment.