Skip to content

Does the HierarchyId is supported for InMemoryDatabase? #32199

@hugoMencoboni

Description

@hugoMencoboni

Do we have a way to use InMemoryDatabase with HierarchyId?

I'm testing the new HierarchyId support of EF Core.

To enable that for SqlServerDatabase, we have to call UseHierarchyId when we setup the DbContext:

		services.AddDbContext<MyDbContext>(options =>
		{
			options.UseSqlServer(connectionString, x => x.UseHierarchyId());
		});

I have a Unit test projet that is using a InMemoryDatabase, but I don't find a way to add an equivalency of that UseHierarchyId that would allow me to unit test code that rely on HierarchyId. Do I miss something?

I think efcore/EFCore.SqlServer.HierarchyId#33 was including that kind of capabilities in the kmataru/EFCore.SqlServer.HierarchyId project, but I don't find that code in https://github.com/dotnet/efcore/tree/main/src/EFCore.InMemory?

Without that support, I'm getting exceptions in my Unit tests:

using Microsoft.EntityFrameworkCore;

namespace HierarchyId.Tests;

public sealed class TestHierarchyIdTests
{
	public class Contact
	{
		public int Id { get; set; }
		public HierarchyId HierarchyId { get; set; }
	}
	public class MyDbContext : DbContext
	{
		public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
		{
		}

		public DbSet<Contact> Contacts { get; set; }

		protected override void OnModelCreating(ModelBuilder modelBuilder)
		{
			base.OnModelCreating(modelBuilder);
			modelBuilder.Entity<Contact>()
				.HasKey(c => c.Id);
			modelBuilder.Entity<Contact>()
				.HasIndex(x => x.HierarchyId)
				.IsUnique();
		}
	}

	[Fact]
	public async Task Test_HierarchyId()
	{
		var inMemoryDbOptions = new DbContextOptionsBuilder<MyDbContext>()
			.UseInMemoryDatabase("Test_HierarchyId")
			.Options;
		var context = new MyDbContext(inMemoryDbOptions);

		var contact = new Contact
		{
			HierarchyId = HierarchyId.Parse("/"),
		};
		await context.Set<Contact>().AddAsync(contact);
	}
}
  Message: 
System.InvalidOperationException : The entity type 'HierarchyId' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.

  Stack Trace: 
  Message: 
    System.InvalidOperationException : The 'HierarchyId' property 'Contact.HierarchyId' could not be mapped because the database provider does not support this type. Consider converting the property value to a type supported by the database using a value converter. See https://aka.ms/efcore-docs-value-converters for more information. Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

  Stack Trace: 
    ModelValidator.ThrowPropertyNotMappedException(String propertyType, IConventionTypeBase typeBase, IConventionProperty unmappedProperty)
    ModelValidator.<ValidatePropertyMapping>g__Validate|7_0(IConventionTypeBase typeBase, <>c__DisplayClass7_0&)
    ModelValidator.ValidatePropertyMapping(IModel model, IDiagnosticsLogger`1 logger)
    ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
    InMemoryModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
    ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
    ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
    DbContextServices.CreateModel(Boolean designTime)
    DbContextServices.get_Model()
    <>c.<TryAddCoreServices>b__8_4(IServiceProvider p)
    <32 more frames...>
    ServiceProviderEngineScope.GetService(Type serviceType)
    ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
    ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
    DbContext.get_DbContextDependencies()
    DbContext.get_ContextServices()
    DbContext.get_InternalServiceProvider()
    DbContext.get_DbContextDependencies()
    DbContext.Set[TEntity]()
    TestHierarchyIdTests.Test_HierarchyId() line 43
    --- End of stack trace from previous location ---

Provider and version information

EF Core version: 8.0.0-rc.2.23480.1
Database provider: Microsoft.EntityFrameworkCore.InMemory
Target framework: .NET 8.0
Operating system: Microsoft Windows 11 Pro
IDE: Microsoft Visual Studio Professional 2022 (64-bit) - Preview

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions