Efcore: Unable to determine the relationship represented by navigation property 'Investor.Wholesalers' of type 'ICollection<Wholesaler>'

Created on 27 Sep 2017  路  4Comments  路  Source: dotnet/efcore

I am having issues with creating a many-to-many relationship in my ASP.net code project.

System.InvalidOperationException: Unable to determine the relationship represented by navigation property 'Investor.Wholesalers' of type 'ICollection<Wholesaler>'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyMappingValidationConvention.Apply(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelBuilt(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.Validate()
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Validate()
   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(IServiceCallSitecallSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSitecallSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSitecallSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSitecallSite, 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)
Unable to determine the relationship represented by navigation property 'Investor.Wholesalers' of type 'ICollection<Wholesaler>'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
### Steps to reproduce
source code location:
https://github.com/SpencerCornelia/Veeya

--- Here's my DBContext Class ---

```C#
using Microsoft.EntityFrameworkCore;
using Veeya.Models;

namespace Veeya.Persistence
{
public class VeeyaDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<InvestorToWholesaler>()
            .HasKey(t => new { t.InvestorId, t.WholesalerId });

        modelBuilder.Entity<InvestorToWholesaler>()
            .HasOne(pt => pt.Investor)
            .WithMany(p => p.InvestorToWholesalers)
            .HasForeignKey(pt => pt.InvestorId);

        modelBuilder.Entity<InvestorToWholesaler>()
            .HasOne(pt => pt.Wholesaler)
            .WithMany(p => p.InvestorToWholesalers)
            .HasForeignKey(pt => pt.WholesalerId);
    }
    public DbSet<Property> Properties { get; set; }
    public DbSet<Wholesaler> Wholesalers { get; set; }
    public DbSet<Investor> Investors { get; set; }
    public DbSet<InvestorToWholesaler> InvestorToWholesalers { get; set; }
    public VeeyaDbContext(DbContextOptions<VeeyaDbContext> options)
        : base(options)
    {
    }
}

}

---Here's my Investor Model---
```C#
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Veeya.Models
{
    [Table("Investors")]
    public class Investor
    {
        public int InvestorId { get; set; }
        public List<InvestorToWholesaler> InvestorToWholesalers { get; set; }

        [Required]
        [StringLength(255)] 
        public string First_Name { get; set; }

        [Required]
        [StringLength(255)]
        public string Last_Name { get; set; }

        [Required]
        [EmailAddress]
        public string Email_Address { get; set; }

        [Required]
        [Phone]
        public string Phone_Number { get; set; }

        public ICollection<Wholesaler> Wholesalers { get; set; }

        public Investor()
        {
            Wholesalers = new Collection<Wholesaler>();
        }

    }
}

---Here's my Wholesaler Model---
```C#
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Veeya.Models
{
[Table("Wholesalers")]
public class Wholesaler
{
public int WholesalerId { get; set; }
public List InvestorToWholesalers { get; set; }

    [Required]
    [StringLength(255)]
    public string First_Name { get; set; }

    public ICollection<Property> Properties { get; set; }

    public ICollection<Investor> Investors { get; set; }

    public Wholesaler() 
    {
        Properties = new Collection<Property>();
        Investors = new Collection<Investor>();
    }
}

}

### Further technical details
EF Core version: (found in project.csproj or packages.config)
```xml
 <ItemGroup>
    <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="1.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
  </ItemGroup>

Operating system: MacOS Sierra 10.12.6
IDE: (e.g. Visual Studio 2015) ---> VSCode 1.16.1

I've tried all the workarounds and tutorials I've come across and haven't seen a solution. It seems like others are having this issue and were unable to find a solution.

I even attempted what some are considering a quick fix and still saw the same errors.

C# modelBuilder.Entity<InvestorToWholesaler>(e => { e.HasOne(r => r.Investor).WithMany(u => u.InvestorToWholesalers).HasForeignKey(r => r.InvestorId); e.HasOne(r => r.Wholesaler).WithMany(u => u.InvestorToWholesalers).HasForeignKey(r => r.WholesalerId); });

closed-duplicate

Most helpful comment

All 4 comments

@SpencerCornelia EF Core doesn't yet support mapping many-to-many collections directly. Instead, there needs to be a join table, which it looks like you are doing with the InvestorToWholesaler class and it's mapping. However, the code still has the direct many-to-many navigation properties:
```C#
public ICollection Wholesalers { get; set; }

```C#
public ICollection<Investor> Investors { get; set; }

These can't be mapped by EF, which is why you are seeing the error. Coincidentally, I just wrote a blog post showing some workarounds that might let you keep these properties--see https://blog.oneunicorn.com/

Closing this as duplicate of #1368

@ajcvickers such a big help. I applied what I learned in your blog and appears to be working. seeing no errors when doing "dotnet ef migrations add XXYYZZ" was wonderful. These issues can be difficult for a beginner such as myself.

@SpencerCornelia EF Core doesn't yet support mapping many-to-many collections directly. Instead, there needs to be a join table, which it looks like you are doing with the InvestorToWholesaler class and it's mapping. However, the code still has the direct many-to-many navigation properties:

 public ICollection<Wholesaler> Wholesalers { get; set; }

and

public ICollection<Investor> Investors { get; set; }

These can't be mapped by EF, which is why you are seeing the error. Coincidentally, I just wrote a blog post showing some workarounds that might let you keep these properties--see https://blog.oneunicorn.com/

Closing this as duplicate of #1368

this helped!!! THNX!!

Use this link https://blog.oneunicorn.com/2017/09/25/many-to-many-relationships-in-ef-core-2-0-part-1-the-basics/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

0xdeafcafe picture 0xdeafcafe  路  189Comments

rowanmiller picture rowanmiller  路  112Comments

divega picture divega  路  100Comments

rowanmiller picture rowanmiller  路  85Comments

obelixA picture obelixA  路  105Comments