【问题标题】:Upgrade to 2.1 breaks existing .net core EF logic升级到 2.1 会破坏现有的 .net 核心 EF 逻辑
【发布时间】:2018-06-04 16:42:30
【问题描述】:

我有 2 个对象之间存在 FK 关系。当我使用 .net core 2 时,所有这些逻辑都运行良好,但当我升级到 2.1 时就坏了

public class Parent
{
     [Key()]
     public Guid ParentGUID {get;set;}
     public string SomeValue {get;set;}
     [ForeignKey("ReferenceTypeGUID")]
     public ReferenceType ReferenceTypeObject {get;set;}
}
public class ReferenceType
{
     [Key()]
     public Guid ReferenceTypeGUID{get;set;}
     public string SomeOtherValue {get;set;}
     public virtual ICollection<Parent> ParentGU { get; set; }
}

然后在我的 dbcontext 中我有

 modelBuilder.Entity<ReferenceType>(entity =>
        {
            entity.HasKey(e => e.ReferenceTypeGUID);

                entity.HasMany(c => c.ParentGU)
                    .WithOne(e => e.ReferenceTypeObject)
                    .HasForeignKey(f => f.ParentGUID)
                    .OnDelete(DeleteBehavior.ClientSetNull);
});

现在在我的原始代码中,我没有 HasForeignKey 行,并且出现以下错误:

无法定位主键,因为它不兼容

添加该行解决了这个问题,但现在我得到了

操作数类型冲突:int 与 uniqueidentifier 不兼容

出于某种原因,EF 假设数据库类型应该是 int 而不是 uniqueidentifier,即使对象被声明为 GUID。我该如何解决这个问题?

【问题讨论】:

  • 您能否修复示例(未编译)。同样显然 PK ParentGUID 不能用作多对一关系的 FK,所以保留原始代码和升级的原始问题。
  • 我假设 net core 2.1 是指 Entity Framework Core 2.1。无法使用提供的代码重现(即使我删除了明显错误的.HasForeignKey 行)。尝试在一个干净的项目中重现它并让我们知道,或者检查此处未显示的代码是否有其他原因。
  • github.com/vishnu4/EFCore21Test。只需运行添加迁移,您就会看到错误:从 'Parent.ReferenceTypeObject' 到 'ReferenceType.ParentGU' 的关系具有外键属性 {'ReferenceTypeGUID' : Nullable} 无法定位主键 {' ReferenceTypeGUID' : Guid} 因为它不兼容。为此关系配置一个主键或一组兼容的外键属性。
  • 谢谢,转载!
  • Parent 中没有包含外键引用的属性。你的父类应该有一个属性public Guid ReferenceTypeGUID { get; set; }。我想你会发现[ForeignKey] 属性期望在同一个类中找到声明的属性名称。

标签: entity-framework asp.net-core entity-framework-core asp.net-core-2.1


【解决方案1】:

当您通过 ForeignKey 注释定义影子 FK 属性时,似乎 EF Core 2.1 引入了一个错误(坦率地说,我根本不知道这是受支持的)。它错误地假定该影子属性为 intint? 类型,而不是考虑引用的 PK 属性类型。

如果您愿意,您可以在他们的问题跟踪器中填写问题。但我不建议为此目的使用ForeignKey 属性(或者根本不建议为关系使用数据注释)。

您可以通过将以下内容添加到Parent 实体流式配置来修复它:

entity.Property<Guid?>("ReferenceTypeGUID");

但如果你想为 shadow 属性配置一个不同的数据库列名,这很有意义。

更好的 (IMO) 方法是删除 ForeignKey 属性并简单地将HasForeignKey 重载与string foreignKeyPropertyNames 参数一起使用:

entity.HasMany(c => c.ParentGU)
    .WithOne(e => e.ReferenceTypeObject)
    .HasForeignKey("ReferenceTypeGUID") // <--
    .OnDelete(DeleteBehavior.ClientSetNull);

【讨论】:

  • 那是为我做的,谢谢。是的,出于某种原因,在业务对象中添加 ForeignKey 属性对我来说感觉更干净。我喜欢尽可能多地添加到业务对象中,并尽可能保持我的 OnModelCreating 精简,但感谢您帮助我让它工作!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-10
  • 2012-04-01
  • 1970-01-01
相关资源
最近更新 更多