Skip to content

Commit

Permalink
Change the message of incorrect entity type exception to include dupl…
Browse files Browse the repository at this point in the history
…icate type with different namespace (#23946)
  • Loading branch information
Ali-YousefiTelori authored Jan 28, 2021
1 parent 2738442 commit ee09fa7
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 5 deletions.
15 changes: 13 additions & 2 deletions src/EFCore/DbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -140,7 +141,8 @@ public virtual ChangeTracker ChangeTracker
/// </summary>
public virtual IModel Model
{
[DebuggerStepThrough] get => DbContextDependencies.Model;
[DebuggerStepThrough]
get => DbContextDependencies.Model;
}

/// <summary>
Expand Down Expand Up @@ -313,7 +315,16 @@ private IEntityFinder Finder(Type type)
throw new InvalidOperationException(CoreStrings.InvalidSetSharedType(type.ShortDisplayName()));
}

throw new InvalidOperationException(CoreStrings.InvalidSetType(type.ShortDisplayName()));
var findSameTypeName = Model.FindSameTypeNameWithDifferentNamespace(type);
//if the same name exists in your entity types we will show you the full namespace of the type
if (!string.IsNullOrEmpty(findSameTypeName))
{
throw new InvalidOperationException(CoreStrings.InvalidSetSameTypeWithDifferentNamespace(type.DisplayName(), findSameTypeName));
}
else
{
throw new InvalidOperationException(CoreStrings.InvalidSetType(type.ShortDisplayName()));
}
}

if (entityType.FindPrimaryKey() == null)
Expand Down
12 changes: 11 additions & 1 deletion src/EFCore/Internal/InternalDbSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Utilities;

Expand Down Expand Up @@ -81,7 +82,16 @@ public override IEntityType EntityType
throw new InvalidOperationException(CoreStrings.InvalidSetSharedType(typeof(TEntity).ShortDisplayName()));
}

throw new InvalidOperationException(CoreStrings.InvalidSetType(typeof(TEntity).ShortDisplayName()));
var findSameTypeName = _context.Model.FindSameTypeNameWithDifferentNamespace(typeof(TEntity));
//if the same name exists in your entity types we will show you the full namespace of the type
if (!string.IsNullOrEmpty(findSameTypeName))
{
throw new InvalidOperationException(CoreStrings.InvalidSetSameTypeWithDifferentNamespace(typeof(TEntity).DisplayName(), findSameTypeName));
}
else
{
throw new InvalidOperationException(CoreStrings.InvalidSetType(typeof(TEntity).ShortDisplayName()));
}
}

if (_entityType.IsOwned())
Expand Down
26 changes: 26 additions & 0 deletions src/EFCore/Metadata/Internal/EntityTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -420,5 +420,31 @@ public static IProperty CheckPropertyBelongsToType([NotNull] this IEntityType en
/// </summary>
public static EntityType AsEntityType([NotNull] this IEntityType entityType, [NotNull] [CallerMemberName] string methodName = "")
=> MetadataExtensions.AsConcreteMetadataType<IEntityType, EntityType>(entityType, methodName);



/// <summary>
/// Try to find the name of the type that has a different namespace from your entity types
/// </summary>
/// <param name="model">
/// model Of your context to find entities
/// </param>
/// <param name="type">
/// A Type that you think have a different namespace and exists in your entity types
/// </param>
/// <returns>
/// the name with different namespace found
/// </returns>
public static string? FindSameTypeNameWithDifferentNamespace([NotNull] this IModel model, [NotNull] Type type)
{
//try to find the same name of the entity with type to throw a specific exception
return model.GetEntityTypes()
//check the short names are equals because the namespaces are not equaled we need to check just names are equals
.Where(x => x.ClrType.DisplayName(false) == type.DisplayName(false))
//select the full name of type because we need to show the developer a type with the full name
.Select(x => x.ClrType.DisplayName())
//select one of them to show the developer
.FirstOrDefault();
}
}
}
13 changes: 11 additions & 2 deletions src/EFCore/Properties/CoreStrings.Designer.cs

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/Properties/CoreStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@
<data name="InvalidSetType" xml:space="preserve">
<value>Cannot create a DbSet for '{typeName}' because this type is not included in the model for the context.</value>
</data>
<data name="InvalidSetSameTypeWithDifferentNamespace" xml:space="preserve">
<value>Cannot create a DbSet for '{typeName}' because this type is not included in the model for the context. However the model contains an entity type with the same name in a different namespace: '{entityTypeName}'.</value>
</data>
<data name="InvalidSetTypeOwned" xml:space="preserve">
<value>Cannot create a DbSet for '{typeName}' because it is configured as an owned entity type and must be accessed through its owning entity type '{ownerType}'.</value>
</data>
Expand Down
32 changes: 32 additions & 0 deletions test/EFCore.Specification.Tests/FindTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;

Expand Down Expand Up @@ -300,11 +301,22 @@ public virtual void Throws_for_bad_type_for_composite_key()
public virtual void Throws_for_bad_entity_type()
{
using var context = CreateContext();

Assert.Equal(
CoreStrings.InvalidSetType(nameof(Random)),
Assert.Throws<InvalidOperationException>(() => Find<Random>(context, 77)).Message);
}

[ConditionalFact]
public virtual void Throws_for_bad_entity_type_with_different_namespace()
{
using var context = CreateContext();

Assert.Equal(
CoreStrings.InvalidSetSameTypeWithDifferentNamespace(typeof(Microsoft.EntityFrameworkCore.DifferentNamespace.ShadowKey).DisplayName(), typeof(ShadowKey).DisplayName()),
Assert.Throws<InvalidOperationException>(() => Find<Microsoft.EntityFrameworkCore.DifferentNamespace.ShadowKey>(context, 77)).Message);
}

[ConditionalFact]
public virtual async Task Find_int_key_tracked_async()
{
Expand Down Expand Up @@ -580,6 +592,17 @@ public virtual async Task Throws_for_bad_entity_type_async()
(await Assert.ThrowsAsync<InvalidOperationException>(() => FindAsync<Random>(context, 77).AsTask())).Message);
}

[ConditionalFact]
public virtual async Task Throws_for_bad_entity_type_with_different_namespace_async()
{
using var context = CreateContext();

Assert.Equal(
CoreStrings.InvalidSetSameTypeWithDifferentNamespace(typeof(Microsoft.EntityFrameworkCore.DifferentNamespace.ShadowKey).DisplayName(), typeof(ShadowKey).DisplayName()),
(await Assert.ThrowsAsync<InvalidOperationException>(() => FindAsync<Microsoft.EntityFrameworkCore.DifferentNamespace.ShadowKey>(context, 77).AsTask())).Message);
}


protected class BaseType
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
Expand Down Expand Up @@ -677,3 +700,12 @@ protected override void Seed(PoolableDbContext context)
}
}
}


namespace Microsoft.EntityFrameworkCore.DifferentNamespace
{
internal class ShadowKey
{
public string Foo { get; set; }
}
}
21 changes: 21 additions & 0 deletions test/EFCore.Tests/DbContextServicesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3678,3 +3678,24 @@ public DerivedContext2(DbContextOptions<DerivedContext2> options)
}
}
}

namespace Microsoft.EntityFrameworkCore.DifferentNamespace
{
internal class Category
{
public int Id { get; set; }
public string Name { get; set; }

public List<Product> Products { get; set; }
}

internal class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }

public int CategoryId { get; set; }
public Category Category { get; set; }
}
}
10 changes: 10 additions & 0 deletions test/EFCore.Tests/DbContextTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,19 @@ public void Set_throws_for_type_not_in_model()

using var context = new DbContext(optionsBuilder.Options);
var ex = Assert.Throws<InvalidOperationException>(() => context.Set<Category>().Local);

Assert.Equal(CoreStrings.InvalidSetType(nameof(Category)), ex.Message);
}

[ConditionalFact]
public void Set_throws_for_type_not_in_model_same_type_with_different_namespace()
{
using var context = new EarlyLearningCenter();
var ex = Assert.Throws<InvalidOperationException>(() => context.Set<Microsoft.EntityFrameworkCore.DifferentNamespace.Category>().Local);

Assert.Equal(CoreStrings.InvalidSetSameTypeWithDifferentNamespace(typeof(Microsoft.EntityFrameworkCore.DifferentNamespace.Category).DisplayName(), typeof(Category).DisplayName()), ex.Message);
}

[ConditionalFact]
public void Local_calls_DetectChanges()
{
Expand Down
1 change: 1 addition & 0 deletions test/EFCore.Tests/DbSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ public void Use_of_LocalView_throws_if_context_is_disposed()
public void Using_ignored_entity_that_has_DbSet_on_context_throws_appropriately()
{
using var context = new IgnoredCntext();

Assert.Equal(
CoreStrings.InvalidSetType(nameof(IgnoredEntity)),
Assert.Throws<InvalidOperationException>(() => context.Ignored.ToList()).Message);
Expand Down

0 comments on commit ee09fa7

Please sign in to comment.