Efcore: Metadata: InverseProperty fails to resolve ambiguity while use KeyAttribute on PK

Created on 14 Jul 2017  路  20Comments  路  Source: dotnet/efcore

I am opening a issue regarding the [Foreignkey] attribute
This was using the Pomelo.MySQL driver, but it might also affect other drivers.

(origional issue) https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/324

Note (as described below) that it worked perfectly fine in EFCore 1.0 and 1.1 and broke in 2.0

Steps to reproduce

  1. Create a test application with the model below
    1 targeting NetCoreApp 1.1
    1 targeting NetCoreApp 2.0
  2. Run "dotnet restore"
  3. Run "dotnet build"
  4. Run "dotnet ef migrations add initial"

Model used

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFModelTest
{
    class Program
    {
        static void Main(string[] args) { }
    }

    public class User
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }

        [MaxLength(64)]
        public string Name { get; set; }

        [InverseProperty(nameof(Relation.AccountManager))]
        public virtual ICollection<Relation> AccountManagerRelations { get; set; }

        [InverseProperty(nameof(Relation.SalesManager))]
        public virtual ICollection<Relation> SalesManagerRelations { get; set; }
    }

    public class Relation
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public string Id { get; set; }

        [MaxLength(64)]
        public string Name { get; set; }

        public int? AccountManagerId { get; set; }

        [ForeignKey(nameof(AccountManagerId))]
        public virtual User AccountManager { get; set; }

        public int? SalesManagerId { get; set; }

        [ForeignKey(nameof(SalesManagerId))]
        public virtual User SalesManager { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<User> Users { get; set; }

        public DbSet<Relation> Relations { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder.UseMySql(@"User Id=root;Password=root;Host=localhost;Database=eftest;Persist Security Info=True;Convert Zero Datetime=True;");
    }
}

The issue

Using data attributes to add a foreign key fails in EFCore 2.0 when the classname is not equal to a property name.

For instance:
Mapping a UserId as foreign key to a class called User using a property User => works fine
Mapping a ManagerId as foreign key to a class called User using a property called Manager => Broken

Stacktrace EF MySQL 1.1

PS D:\Sourcecodes\EF Core MySQL\NET1.1> dotnet ef migrations add initial

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.39
Done. To undo this action, use 'ef migrations remove'

Migration model

.....
   migrationBuilder.CreateTable(
                name: "Relations",
                columns: table => new
                {
                    Id = table.Column<string>(nullable: false),
                    AccountManagerId = table.Column<int>(nullable: true),
                    Name = table.Column<string>(maxLength: 64, nullable: true),
                    SalesManagerId = table.Column<int>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Relations", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Relations_Users_AccountManagerId",
                        column: x => x.AccountManagerId,
                        principalTable: "Users",
                        principalColumn: "UserId",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Relations_Users_SalesManagerId",
                        column: x => x.SalesManagerId,
                        principalTable: "Users",
                        principalColumn: "UserId",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateIndex(
                name: "IX_Relations_AccountManagerId",
                table: "Relations",
                column: "AccountManagerId");

            migrationBuilder.CreateIndex(
                name: "IX_Relations_SalesManagerId",
                table: "Relations",
                column: "SalesManagerId");

Stacktrace EF MySQL 2.0

PS D:\Sourcecodes\Model Scaffolding Error\NET2.0> dotnet ef migrations add initial
System.InvalidOperationException: Unable to determine the relationship represented by navigation property 'Relation.AccountManager' of type 'User'. 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.VisitFactoryService(FactoryService factoryService, 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.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.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.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.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__DisplayClass17_0.<RealizeService>b__0(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Design.Internal.DesignTimeServicesBuilder.<>c__DisplayClass6_0.<ConfigureContextServices>b__7(IServiceProvider _)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactoryService(FactoryService factoryService, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitTransient(TransientCallSite transientCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass17_0.<RealizeService>b__0(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.EnsureServices(IServiceProvider services)
   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 'Relation.AccountManager' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Workaround

Using the fluent api to add the constraint fixes the issue, its purely data attribute constraints that can't be resolved.

Adding the below modelbuilder to the MyContext fixes the issue in EF Core 2.0
This was not required in 1.1

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<Relation>(e =>
    {
       e.HasOne(r => r.AccountManager).WithMany(u => u.AccountManagerRelations).HasForeignKey(r => r.AccountManagerId);
       e.HasOne(r => r.SalesManager).WithMany(u => u.SalesManagerRelations).HasForeignKey(r => r.SalesManagerId);
    });
}

Output with workaround

PS D:\Sourcecodes\Model Scaffolding Error\NET2.0> dotnet ef migrations add initial
Done. To undo this action, use 'ef migrations remove'

Scaffolds just fine

Further technical details

MySQL version: 5.7.14
Operating system: Windows Server 2012
Pomelo.EntityFrameworkCore.MySql version: 1.1.2 & 2.0.0-preview2-10046

Other details about my project setup:
Visual Studio 2017 Preview 4

closed-fixed regression type-bug

Most helpful comment

In case anyone needs it, here is a quick fix that works for me (not thoroughly tested for all scenarios, and by no means meant to be efficient for long term):

```
///


/// Temporarily fixes a bug with InverseProperty attribute being ignored: https://github.com/aspnet/EntityFrameworkCore/issues/9180
///

public static void InversePropertyPatchEF20(ModelBuilder modelBuilder) where TContext : DbContext
{
// (need a patch to fix the InverseProperty issue in EF 2.0)

// ... get all 'DbSet<>' properties from the given context and extract the entity types ...

var modelTypes = (from t in typeof(TContext).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
                    where t.PropertyType.IsGenericType && t.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)
                    select t.PropertyType.GenericTypeArguments[0]);

foreach (var modelType in modelTypes)
{
    // ... find all properties with InversePropertyAttribute and handle it ...

    var ipProperties = (from p in modelType.GetProperties()
                        where p.GetCustomAttribute<InversePropertyAttribute>() != null && p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
                        select p);

    foreach (var prop in ipProperties)
    {
        var otherModelType = prop.PropertyType.GenericTypeArguments[0]; // (gets the ICollection<T> generic parameter type (T), which points to the entity model on the other end)
        var ipAttr = prop.GetCustomAttribute<InversePropertyAttribute>();
        modelBuilder.Entity(modelType).HasMany(otherModelType, prop.Name).WithOne(ipAttr.Property);
    }
}

}


Requirements:  Make sure you have the `[InverseProperty(...)]` attrbiute on your `ICollection<T>` navigational properties where needed (do not have this attribute both ends). Why on the collection?  Because it's easier to filter by looking for the generic collection `ICollection<T>` and hard code Many-To-One instead of trying to detect the reverse as well.  When this is no longer needed, removing this method should be all you need to do and it will still work as it should.

Usage example: 

public partial class MyDBContextType // : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
... many-to-many fluent mappings for "map" types ...
InversePropertyPatchEF20(modelBuilder);
base.OnModelCreating(modelBuilder);
}
...
```
I have 75 tables so far (many more coming) in a complex weave of many-to-many mappings, and it works like a charm; now I can continue. 8)

All 20 comments

The 2.0 preview version of the Pomelo MySQL provider here uses Microsoft.EntityFrameworkCore.Relational version 2.0.0-preview2-final

Note for triage: this repros with the SQL Server provider and is a regression from 1.1.2.

Condensed model
```C#
public class User
{
[Key]
public int UserId { get; set; }

[InverseProperty(nameof(Relation.AccountManager))]
public virtual ICollection<Relation> AccountManagerRelations { get; set; }

[InverseProperty(nameof(Relation.SalesManager))]
public virtual ICollection<Relation> SalesManagerRelations { get; set; }

}

public class Relation
{
public string Id { get; set; }

public virtual User AccountManager { get; set; }
public virtual User SalesManager { get; set; }

}
```

Work-around remove KeyAttribute from User.UserId property. It will be marked as PK by convention so it creates the same model as you posted in migration.

Can somebody tell me that Scaffolding of database is able to done or not in latest IDE of visual studio 2017 preview 4?

Unable to determine the relationship represented by navigation property occurring issue after migration of asp.net core 1.1 to 2.0

We are having the same issue in our projects. Would appreciate a decent workaround if available and a quick fix. Maybe also update test cases to avoid this regression.

@abhijitajmera The workaround is in the first comment, you need to configure the relationship using Fluent API

@AndriySvyryd Thanks. The work around worked well. Thanks.

@AndriySvyryd Do you think this meets the bar to patch in 2.0.1?

@ajcvickers No, the fix would have a non-trivial risk of causing other regressions.

I just ran into a same/similar issue. My perfectly working EF setup now fails once I moved to Core 2.0.

InvalidOperationException: Unable to determine the relationship represented by navigation property 'SomeTable.NavProperty' of type 'ICollection'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

It no longer recognizes the InverseProperty attributes I have helping to prevent the ambiguity issues. Manually mapping it using the fluent API works just fine. I'm tempted now to write a quick patch using reflection to find and map this automatically, as I have way too many tables to undo all this and put back later when it does work.

_(note: I'm also using Pomelo.EntityFrameworkCore.MySql)_

In case anyone needs it, here is a quick fix that works for me (not thoroughly tested for all scenarios, and by no means meant to be efficient for long term):

```
///


/// Temporarily fixes a bug with InverseProperty attribute being ignored: https://github.com/aspnet/EntityFrameworkCore/issues/9180
///

public static void InversePropertyPatchEF20(ModelBuilder modelBuilder) where TContext : DbContext
{
// (need a patch to fix the InverseProperty issue in EF 2.0)

// ... get all 'DbSet<>' properties from the given context and extract the entity types ...

var modelTypes = (from t in typeof(TContext).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
                    where t.PropertyType.IsGenericType && t.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)
                    select t.PropertyType.GenericTypeArguments[0]);

foreach (var modelType in modelTypes)
{
    // ... find all properties with InversePropertyAttribute and handle it ...

    var ipProperties = (from p in modelType.GetProperties()
                        where p.GetCustomAttribute<InversePropertyAttribute>() != null && p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
                        select p);

    foreach (var prop in ipProperties)
    {
        var otherModelType = prop.PropertyType.GenericTypeArguments[0]; // (gets the ICollection<T> generic parameter type (T), which points to the entity model on the other end)
        var ipAttr = prop.GetCustomAttribute<InversePropertyAttribute>();
        modelBuilder.Entity(modelType).HasMany(otherModelType, prop.Name).WithOne(ipAttr.Property);
    }
}

}


Requirements:  Make sure you have the `[InverseProperty(...)]` attrbiute on your `ICollection<T>` navigational properties where needed (do not have this attribute both ends). Why on the collection?  Because it's easier to filter by looking for the generic collection `ICollection<T>` and hard code Many-To-One instead of trying to detect the reverse as well.  When this is no longer needed, removing this method should be all you need to do and it will still work as it should.

Usage example: 

public partial class MyDBContextType // : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
... many-to-many fluent mappings for "map" types ...
InversePropertyPatchEF20(modelBuilder);
base.OnModelCreating(modelBuilder);
}
...
```
I have 75 tables so far (many more coming) in a complex weave of many-to-many mappings, and it works like a charm; now I can continue. 8)

@rjamesnw I was having issues with your patch. First thing I noticed; this requires all Models to be [Table("Name")] tagged. Also, the .ToTable() method takes a string, which could be fixed by using .ToTable(modelType.Name), but that assumes Table name == Model name.

I updated mine with the following change and it works like a charm now. Does it make sense, or is there a better way? I'm still a rookie with reflection.

modelBuilder.Entity(modelType).ToTable(modelType.GetCustomAttribute<TableAttribute>().Name)
                        .HasMany(otherModelType, prop.Name).WithOne(ipAttr.Property);

Sorry, .ToTable(Type) was my own custom extension method, forgot about that. I had a custom convention to deal with table names. Also, yes, all my entities have the table attribute, it was a quick and dirty fix for me.

The code is now updated to work properly, and no longer requires the Table attribute. It checks the DbSet<> properties on the context instead in order to get the entity model types. You probably don't need ToTable() either since the EF should figure this out implicitly, so I removed it.

Hi @Giantaxe, @varora1406, @rjamesnw, @asleight, and @abhijitajmera. We are gathering information on the use of EF Core pre-release builds. You reported this issue shortly after the release of 2.0.0 RTM. It would be really helpful if you could let us know:

  • Did you consider testing your code against the pre-release builds?
  • Was there anything blocking you from using pre-release builds?
  • What do you think could make it easier for you to use pre-release builds in the future?

Thanks in advance for any feedback. Hopefully this will help us to increase the value of pre-release builds going forward.

Did anyone also have a problem with EF Core not being able to distinguish between the two foreign keys when persisting the data in the database?

I have a similar scenario with two one-to-many relations between the same entities in my model but when I save my changes to the DB, the same foreing key is used in both columns. I am using SQL server.

As shown here:
relations

I have created this simple project to show how to reproduce the issue.

public class User {

    [Key]
    public int Id { get; set; }

    [InverseProperty(nameof(UserRelation.Relation1))]
    public Collection<UserRelation> Relations1 { get; set; }

    [InverseProperty(nameof(UserRelation.Relation2))]
    public Collection<UserRelation> Relations2 { get; set; }


}

public class UserRelation {

    [Key]
    public int Id { get; set; }

    public int Relation1Id { get; set; }

    [ForeignKey(nameof(Relation1Id))]
    public User Relation1 { get; set; }

    public int Relation2Id{ get; set; }

    [ForeignKey(nameof(Relation2Id))]
    public User Relation2 { get; set; }

}

On my DbContext I also have:

protected override void OnModelCreating(ModelBuilder modelBuilder) {
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<UserRelation>(e => {
        e.HasOne(r => r.Relation1).WithMany(u => u.Relations1).HasForeignKey(r => r.Relation1Id).OnDelete(DeleteBehavior.ClientSetNull);
        e.HasOne(r => r.Relation2).WithMany(u => u.Relations2).HasForeignKey(r => r.Relation2Id).OnDelete(DeleteBehavior.ClientSetNull);
    });
}

You can find the whole demo project attached. I'm using Visual Studio 2017 Preview 2
TestCoreApp.zip

Are there any workarounds available is this an known issue? It seems to be connected to this one, but not exactly the same problem.

@brunopessanha - I downloaded the zip file and examined the code.
Following code
C# user1.Relations1 = new System.Collections.ObjectModel.Collection<UserRelation>(); user1.Relations1.Add(new UserRelation() { Relation1Id = user2.Id, Relation2Id = user1.Id }); user1.Relations1.Add(new UserRelation() { Relation1Id = user3.Id, Relation2Id = user1.Id }); user1.Relations1.Add(new UserRelation() { Relation1Id = user4.Id, Relation2Id = user1.Id });
Even though you are setting Relation1Id to different values you are still adding all those UserRelations to user1.Relations1 collection. Once you add UserRelation to user1.Relation1 collection, navigation fixup will kick in and it will set Relation1Id (FK associated with navigation) to PK of user1. Hence for all the UserRelations the Relation1Id has value of user1.Id

The log should be adjusted. At the moment, it doesn't fail (I think) but there are plenty of lines in the log that say it did fail...

Entity Framework Core 2.1.0-preview2-30271 initialized 'DbContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: SensitiveDataLoggingEnabled MaxPoolSize=128 StoreName=DataAnnotations 
Relationship from 'Relation' to 'User' not configured because there are multiple properties on one entity type {'AccountManager', 'SalesManager'} that could be matched with the properties on the other entity type {'AccountManagerRelations', 'SalesManagerRelations'}.
Relationship from 'User' to 'Relation' not configured because there are multiple properties on one entity type {'AccountManagerRelations'} that could be matched with the properties on the other entity type {'AccountManager'}.
Relationship from 'User' to 'Relation' not configured because there are multiple properties on one entity type {'SalesManagerRelations'} that could be matched with the properties on the other entity type {'SalesManager'}.
The best match for foreign key properties {'Id' : string} are incompatible with the principal key {'UserUId' : int}.
The best match for foreign key properties {'Id' : string} are incompatible with the principal key {'UserUId' : int}.
Relationship from 'Relation' to 'User' not configured because there are multiple properties on one entity type {'AccountManager'} that could be matched with the properties on the other entity type {'AccountManagerRelations'}.
Relationship from 'Relation' to 'User' not configured because there are multiple properties on one entity type {'SalesManager'} that could be matched with the properties on the other entity type {'SalesManagerRelations'}.
Relationship from 'User' to 'Relation' not configured because there are multiple properties on one entity type {'AccountManagerRelations'} that could be matched with the properties on the other entity type {'AccountManager'}.
Relationship from 'User' to 'Relation' not configured because there are multiple properties on one entity type {'SalesManagerRelations'} that could be matched with the properties on the other entity type {'SalesManager'}.
Relationship from 'Relation' to 'User' not configured because there are multiple properties on one entity type {'AccountManager'} that could be matched with the properties on the other entity type {'AccountManagerRelations'}.
Relationship from 'Relation' to 'User' not configured because there are multiple properties on one entity type {'SalesManager'} that could be matched with the properties on the other entity type {'SalesManagerRelations'}.
Relationship from 'User' to 'Relation' not configured because there are multiple properties on one entity type {'AccountManagerRelations'} that could be matched with the properties on the other entity type {'AccountManager'}.
Relationship from 'User' to 'Relation' not configured because there are multiple properties on one entity type {'SalesManagerRelations'} that could be matched with the properties on the other entity type {'SalesManager'}.
Entity Framework Core 2.1.0-preview2-30271 initialized 'DbContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: SensitiveDataLoggingEnabled MaxPoolSize=128 StoreName=DataAnnotations

@yanchenw These log messages do not indicate errors; they are messages out of the model building conventions mechanisms describing what was discovered about the model as it is being processed by the conventions. The log level for these messages will be bumped down to "debug" as part of #10966.

Was this page helpful?
0 / 5 - 0 ratings