Skip to content

Allow defining indexes (and keys) across complex/owned types #11336

@lzocateli

Description

@lzocateli

I need to generate migration for my entity "Contact" has the "Complex Type -> Address".

So far so good!

However, in the "Contact" entity I need to create a unique index containing "Complex Type -> Address" properties, which is causing migration error.

How can I create this unique index?

The code with example is in:
https://github.com/lincolnzocateli/EFCoreExample/blob/master/Map/ContactMap.cs

using System.Linq;
using EfCoreExample.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace EfCoreExample.Map
{

    public class ContactMap : IEntityTypeConfiguration<Contact>
    {


        public void Configure(EntityTypeBuilder<Contact> builder)
        {

            builder.ToTable("Contacts");


            builder.HasKey(x => x.ContactId);

            builder.Property(x => x.ContactId)
                .IsRequired();

            
            builder.Property(x => x.Name)
                .IsRequired()
                .HasColumnType("varchar(40)");

            builder.Property(x => x.Observation)
                .HasColumnType("varchar(100)");

            builder.OwnsOne(x => x.Address).Property(x => x.AddressType)
                .IsRequired()
                .HasColumnType($"varchar(20)")
                .HasColumnName("Type");

            builder.OwnsOne(x => x.Address).Property(x => x.Street)
                .IsRequired()
                .HasColumnType($"varchar(60)")
                .HasColumnName("Street");

            builder.OwnsOne(x => x.Address).Property(x => x.Neighborhood)
                .HasColumnType($"varchar(60)")
                .HasColumnName("Complement");

            builder.OwnsOne(x => x.Address).Property(x => x.City)
                .IsRequired()
                .HasColumnType($"varchar(60)")
                .HasColumnName("City");

            builder.OwnsOne(x => x.Address).Property(x => x.State)
                .IsRequired()
                .HasColumnType($"varchar(2)")
                .HasColumnName("State");

            builder.OwnsOne(x => x.Address).Property(x => x.Zip)
                .IsRequired()
                .HasColumnType($"varchar(8)")
                .HasColumnName("ZipCode");

            //(1:N)
            builder.HasOne(x => x.Person)
                .WithMany(c => c.Contacts)
                .HasForeignKey(x => x.ContactId)
                .OnDelete(DeleteBehavior.Restrict);



           builder.HasIndex(e => new
               {
                   e.Name,
                   e.Address.AddressType,
                   e.Address.Zip,
               }).HasName("IX_MyIndex")
               .IsUnique();

        }
    }

}

Exception message:

The properties expression 'e => new <>f__AnonymousType1`3(Name = e.Name, AddressType = e.Address.AddressType, Zip = e.Address.Zip)' is not valid. The expressionshould represent a property access: 't => t.MyProperty'. When specifying multiple properties use an anonymous type: 't => new { t.MyProperty1, t.MyProperty2 }'.
Parameter name: propertyAccessExpression
Stack trace:
System.ArgumentException: The properties expression 'e => new <>f__AnonymousType1`3(Name = e.Name, AddressType = e.Address.AddressType, Zip = e.Address.Zip)' isnot valid. The expression should represent a property access: 't => t.MyProperty'. When specifying multiple properties use an anonymous type: 't => new { t.MyProperty1, t.MyProperty2 }'.
Parameter name: propertyAccessExpression
   at Microsoft.EntityFrameworkCore.Internal.ExpressionExtensions.GetPropertyAccessList(LambdaExpression propertyAccessExpression)
   at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder`1.HasIndex(Expression`1 indexExpression)
   at EfCoreExample.Map.ContactMap.Configure(EntityTypeBuilder`1 builder) in /home/lincoln/Dropbox/EFCoreExample/Map/ContactMap.cs:line 70
   at Microsoft.EntityFrameworkCore.ModelBuilder.ApplyConfiguration[TEntity](IEntityTypeConfiguration`1 configuration)
   at EfCoreExample.Context.EfCoreExampleContext.OnModelCreating(ModelBuilder modelBuilder) in /home/lincoln/Dropbox/EFCoreExample/Context/EfExampleContext.cs:line 37
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.<>c__DisplayClass5_0.<GetModel>b__0(Object k)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_1(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.<RealizeService>b__0(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_1.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

Steps to reproduce

Generate migration for the first time:
/> dotnet ef migrations add v1.0.0

Further technical details

EF Core version:
Microsoft.EntityFrameworkCore.Design version 2.0.1
Microsoft.EntityFrameworkCore.Tools.DotNet version 2.0.1
Database Provider: Microsoft.EntityFrameworkCore.SqlServer version 2.0.1
Operating system: Linux Debian 9
IDE: VSCODE

Metadata

Metadata

Assignees

No fields configured for Feature.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions