即使使用注释,实体框架核心也无法解析逆属性

时间:2017-10-15 01:58:12

标签: c# entity-framework entity-framework-6 entity-framework-core

我把它归结为一个非常小的用例:

public class ItemRental
{
    [Key]
    public Int32 ItemRentalId { get; set; }

    public Int32? OriginatingSalesOrderId { get; set; }

    [ForeignKey("OriginatingSalesOrderId")]
    public SalesOrder OriginatingSalesOrder { get; set; }

    public Int32? DepositCreditedOnSalesOrderId { get; set; }

    [ForeignKey("DepositCreditedOnSalesOrderId")]
    public SalesOrder DepositCreditedOnSalesOrder { get; set; }
}

public class SalesOrder
{

    [Key]
    public Int32 SalesOrderId { get; set; }

    [InverseProperty("OriginatingSalesOrder")]
    public ICollection<ItemRental> Rentals { get; set; }


    [InverseProperty("DepositCreditedOnSalesOrder")]
    public ICollection<ItemRental> Refunds { get; set; }
}

public class MyAppDatabase : DbContext
{
    public MyAppDatabase(DbContextOptions<MyAppDatabase> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(x => x.GetForeignKeys()))
        {
            relationship.DeleteBehavior = DeleteBehavior.Restrict;
        }
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<ItemRental> ItemRentals { get; set; }
    public DbSet<SalesOrder> SalesOrders { get; set; }
}

尝试运行迁移将提供:

  

System.InvalidOperationException:无法确定导航属性&#39; ItemRental.OriginatingSalesOrder&#39;表示的关系。类型&#39; SalesOrder&#39;。手动配置关系,或使用&#39; [NotMapped]&#39;忽略此属性。属性或使用&#39; EntityTypeBuilder.Ignore&#39;在&#39; OnModelCreating&#39;。

对于EF 6.x,这种关系完全没问题。我相信我可以使用Fluent API解决这个问题,但我更愿意了解如何使用注释来完成这项工作。

我在这里找到了一个类似的问题:EntityFramework core model relationship issue while doing Add-Migration但它并没有解决这个问题。

编辑:示例解决方案:https://drive.google.com/file/d/0BzgvtZfXt8MHd1RseVJubmd6TEU/view?usp=sharing

2 个答案:

答案 0 :(得分:5)

这里没有什么可以理解的,因为您的数据注释是完全有效的。

问题的原因更为简单 - 在EFC问题跟踪器中由#9180 Metadata: InverseProperty fails to resolve ambiguity while use KeyAttribute on PK未解决的问题跟踪的EF Core 2.0(回归)错误,计划在下一个2.1版本中发布。

在此之前,链接中建议的解决方法是使用流畅的API,但如果您从Key中的SalesOrderId属性中删除SalesOrder属性,它也可以使用(因为它很幸运地遵循公认的PK公约之一):

public class SalesOrder
{    
    public Int32 SalesOrderId { get; set; }    
    // ...
}

或者如果您对集合导航属性应用InverseProperty属性:

public class ItemRental
{
    // ...
    [ForeignKey("OriginatingSalesOrderId")]
    [InverseProperty("Rentals")]
    public SalesOrder OriginatingSalesOrder { get; set; } 
    // ...    
    [ForeignKey("DepositCreditedOnSalesOrderId")]
    [InverseProperty("Refunds")]
    public SalesOrder DepositCreditedOnSalesOrder { get; set; }
}

答案 1 :(得分:0)

伊万是完全正确的。

我使用下一个简单的方法来避免这个问题(通过这种方式你不需要重命名一个列):

public class ItemRental
{
    [Column("ItemRentalId")] //new
    public Int32 Id { get; set; } //new

    public Int32? OriginatingSalesOrderId { get; set; }

    [ForeignKey("OriginatingSalesOrderId")]
    public SalesOrder OriginatingSalesOrder { get; set; }

    public Int32? DepositCreditedOnSalesOrderId { get; set; }

    [ForeignKey("DepositCreditedOnSalesOrderId")]
    public SalesOrder DepositCreditedOnSalesOrder { get; set; }
}

public class SalesOrder
{
    [Column("SalesOrderId")] //new
    public Int32 Id { get; set; } //new

    [InverseProperty("OriginatingSalesOrder")]
    public ICollection<ItemRental> Rentals { get; set; }

    [InverseProperty("DepositCreditedOnSalesOrder")]
    public ICollection<ItemRental> Refunds { get; set; }
}

public class MyAppDatabase : DbContext
{
    public MyAppDatabase(DbContextOptions<MyAppDatabase> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(x => x.GetForeignKeys()))
        {
            relationship.DeleteBehavior = DeleteBehavior.Restrict;
        }
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<ItemRental> ItemRentals { get; set; }
    public DbSet<SalesOrder> SalesOrders { get; set; }
    }