实体框架 - 列名“*_ID”无效

Posted

技术标签:

【中文标题】实体框架 - 列名“*_ID”无效【英文标题】:Entity Framework - Invalid Column Name '*_ID" 【发布时间】:2013-11-26 09:03:33 【问题描述】:

我已将此范围缩小到 Code First 和 Database first EF 之间的一些问题,但我不确定如何解决它。我会尽量说清楚,但老实说,我自己在这里缺少一些理解。这是实体框架 4.4

我继承了一个使用 Entity Framework 的项目,但许多实际文件已被删除,无法返回。我重新添加了 EF(首先是数据库)并复制了围绕该项目构建的 T4 设置。它生成所有数据库模型的代码版本和一个 DBContext 代码文件。

如果我的连接字符串看起来像“正常”的 .NET 连接字符串,我会收到关于无效列名称“ProcessState_ID”不存在的错误。 ProcessState_ID 根本不在代码库中,也不在 EDMX 文件或任何东西中。这似乎是查询中的一些自动 EF 转换。

当我使连接字符串与实体框架模型匹配时,它可以正常工作。

现在在尝试将之前的代码与 Entity Framework 匹配时,我想保留“正常”的 .NET 连接字符串。

所以我在这里有两个问题: 1.在代码中从普通连接字符串到EF连接字符串的好方法是什么? 2. 这里是否有其他修复我没有看到停止无效列名错误?

【问题讨论】:

如果您的导航属性只有一个 get 访问器,也会发生这种情况:public virtual Person Person get; 请标记答案 【参考方案1】:

我忘记将导航属性标记为虚拟

public Guid GroupId  get; set; 
public Group Group  get; set; 

->

public Guid GroupId  get; set; 
public virtual Group Group  get; set; 

【讨论】:

【参考方案2】:

如果您的表没有任何一对多关系,我的问题是我有一个引用旧的/不存在的列的 MS SQL 触发器。

【讨论】:

【参考方案3】:

我通过实施这个解决方案解决了这个问题

https://jeremiahflaga.github.io/2020/02/16/entity-framework-6-error-invalid-column-name-_id/

简历>

modelBuilder.Entity<Friendship>()
         .ToTable("Friendship")
         .HasKey(x => new  x.Person1Id, x.Person2Id )
         .HasRequired(x => x.PersonOne)
            .WithMany()
            .HasForeignKey(x => x.Person1Id); // WRONG, “Invalid column name ‘Person_Id’.”

modelBuilder.Entity<Friendship>()
         .ToTable("Friendship")
         .HasKey(x => new  x.Person1Id, x.Person2Id )
         .HasRequired(x => x.PersonOne)
            .WithMany(x => x.Friendships) 
            .HasForeignKey(x => x.Person1Id); 

// The solution is to add .WithMany(x => x.Friendships) in your configuration

【讨论】:

【参考方案4】:

我的问题与桌子上的自定义触发器有关

【讨论】:

【参考方案5】:

我终于明白了。

我首先在做 EF6 数据库,我想知道“未知列的范围”错误 - 它出于某种原因生成表名下划线列名,并试图找到一个不存在的列。

在我的例子中,我的一个表有两个外键引用另一个表中的相同主键 - 像这样:

Animals            Owners
=======            ======
AnimalID (PK)      Pet1ID    <- FK to AnimalID
                   Pet2ID    <- also FK to AnimalID

EF 生成了一些奇怪的列名,例如 Owners_AnimalID1Owners_AnimalID2,然后自行中断。

这里的诀窍是这些令人困惑的外键需要使用 Fluent API 向 EF 注册!

在您的主数据库上下文中,覆盖 OnModelCreating 方法并更改实体配置。最好有一个扩展 EntityConfiguration 类的单独文件,但您可以内联。

不管你怎么做,你都需要添加这样的东西:

public class OwnerConfiguration : EntityTypeConfiguration<Owner>

    public OwnerConfiguration()
    
        HasRequired(x => x.Animals)
            .WithMany(x => x.Owners)  // Or, just .WithMany()
            .HasForeignKey(x => x.Pet1ID);
    

这样,EF 将(也许)开始按您的预期工作。轰隆隆。

此外,如果您将上述内容与可为空的列一起使用,您将得到同样的错误 - 只需使用 .HasOptional() 而不是 .HasRequired()


这里的链接让我大吃一惊:

https://social.msdn.microsoft.com/Forums/en-US/862abdae-b63f-45f5-8a6c-0bdd6eeabfdb/getting-sqlexception-invalid-column-name-userid-from-ef4-codeonly?forum=adonetefx

然后,Fluent API 文档提供帮助,尤其是外键示例:

http://msdn.microsoft.com/en-us/data/jj591620.aspx

您也可以将配置放在密钥的另一端,如下所述:

http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx.

我现在遇到了一些新问题,但那是缺失的巨大概念差距。希望对您有所帮助!

【讨论】:

非常感谢。我遇到了同样的问题。 这对我也有用,在地图文件中添加了类似的代码行:builder.HasOne(item =&gt; item.LogicalShipment).WithMany(s =&gt; s.Items).HasForeignKey(item =&gt; item.LogicalShipmentId).IsRequired(); 我遇到了一个与此非常相似的问题。在我的例子中,TableA 有一个指向 TableB 的外键,而 TableB 有 List 我想在程序上填充它。我必须进行以下配置:this.HasRequired( x =&gt; x.TableB ).WithMany( x =&gt; x.TableA ).HasForeignKey( x =&gt; x.TableBId ).WillCascadeOnDelete( true ); 非常感谢!【参考方案6】:

如果您在同一张表上的导航属性存在此问题,则必须更改我们属性的名称。

例如:

Table : PERSON
Id
AncestorId (with a foreign key which references Id named Parent) 

您必须将AncestorId 更改为PersonId

似乎 EF 正在尝试创建密钥 ParentId,因为它找不到名为 Ancestor 的表...

编辑:这是对数据库的修复!

【讨论】:

【参考方案7】:

就我而言,我已经有一个数据库(数据库优先)。感谢这里的所有 cmets,我找到了我的解决方案:

表必须有关系,但列的名称需要不同并添加ForeignKey属性。

[ForeignKey("PrestadorId")] 公共虚拟 AwmPrestadoresServicios Colaboradores 获取;放;

即PRE_ID是PK,而另一张表中的FK是PRESTADOR_ID,那么就可以了。感谢这里的所有 cmets,我找到了我的解决方案。 EF 以神秘的方式工作。

【讨论】:

【参考方案8】:

对我来说,这是因为 EF 的多元化问题。对于以“-Status”之类结尾的表,EF 认为它的单数是“-Statu”。将实体和数据库表名更改为“-StatusTypes”修复了它。

这样,您无需在每次更新实体模型时重命名它。

【讨论】:

【参考方案9】:

在我的情况下,导致此问题的原因是迁移的数据库上缺少 FOREIGN KEY 约束。所以现有的虚拟ICollection没有加载成功。

【讨论】:

【参考方案10】:

在我的情况下,我的种子方法数据仍在调用在先前迁移中已删除的表列。如果您使用 Automapper,请仔细检查您的映射。

【讨论】:

【参考方案11】:

对我来说,这种行为的原因是由于使用 Fluent API 定义的映射存在问题。 我有 2 种相关类型,其中类型 A 有可选的类型 B 对象,类型 B 有许多 A 对象。

public class A 

    …
    public int? BId get; set;
    public B NavigationToBProperty get; set;

public class B

    …
    public List<A> ListOfAProperty get; set;

我已经用 fluent api 定义了这样的映射:

A.HasOptional(p=> p.NavigationToBProperty).WithMany().HasForeignKey(key => key.BId);

但问题是,B 类有导航属性List&lt;A&gt;,所以我有SQLException Invalid column name A_Id

我将 Visual Studio Debug 附加到 EF DatabaseContext.Database.Log 以将生成的 SQL 输出到 VS 输出->调试窗口

db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

并且生成的 SQL 有 2 个来自 B 表的关系 -> 一个具有正确的 id,另一个具有 A_Id

问题的问题在于,我没有将这个 B.List&lt;A&gt; 导航属性添加到映射中。

所以在我的情况下,正确的映射必须是这样的:

A.HasOptional(p=> p.NavigationToBProperty).WithMany(x => x.ListOfAProperty).HasForeignKey(key => key.BId);

【讨论】:

【参考方案12】:

假设:

Table OtherTable OtherTable_ID

现在选择以下方式之一:


A)

删除ICollection&lt;Table&gt;

如果您在检索Table 时遇到与OtherTable_ID 相关的错误,请转到您的OtherTable 模型并确保其中没有ICollection&lt;Table&gt;。如果没有定义关系,框架将自动假定您必须具有对 OtherTable 的 FK,并在生成的 SQL 中创建这些额外的属性。

这个答案的所有信用都属于@LUKE。上面的答案是他在@drewid 答案下的评论。我认为他的评论非常干净,然后我将其重写为答案。


B)

OtherTableId 添加到Table

在数据库中的Table 中定义OtherTableId

【讨论】:

这样一个绝妙的答案! 这个答案确实很快保存了一天。感谢卢克,我确实阅读了他的评论。尽管@drewid 排在了答案链的最后,但它非常棒,并且是大多数人面临这种​​情况所需要的。【参考方案13】:

对于那些(像我一样)没有立即理解其他 2 个答案的人来说,这是一个较晚的条目。

所以...

EF 正在尝试从 PARENT TABLES KEY-REFERENCE 映射到 EXPECTED 名称...因为...数据库 CHILD TABLE 关系中的 FOREIGN KEY 名称已“更改或缩短”...您将获得上面的消息。

(此修复可能因 EF 版本而异)

对我来说修复是: 在模型中添加“ForeignKey”属性

public partial class Tour

    public Guid Id  get; set; 

    public Guid CategoryId  get; set; 

    [Required]
    [StringLength(200)]
    public string Name  get; set; 

    [StringLength(500)]
    public string Description  get; set; 

    [StringLength(50)]
    public string ShortName  get; set; 

    [StringLength(500)]
    public string TourUrl  get; set; 

    [StringLength(500)]
    public string ThumbnailUrl  get; set; 

    public bool IsActive  get; set; 

    [Required]
    [StringLength(720)]
    public string UpdatedBy  get; set; 

    [ForeignKey("CategoryId")]
    public virtual TourCategory TourCategory  get; set; 

【讨论】:

这对我有用。 +1 是我唯一找到此答案的地方。 @Jerry 我定义了外键。但它仍然搜索Category_Id。您已经提到了针对不同版本 EF 的修复,对吧?我正在使用 EF 6.0 我可以采用什么修复方法? @ajay-aradhya 实际上,是最初回复的人,零号犯人,对不同版本的 EF 发表了评论。 @JerryBenson-Montgomery 没关系!我让它工作。正是“一对一”映射导致它搜索*_ID。包括反向引用工作正常。 您也可以通过添加元数据部分类来解决此问题,这样您在重新生成时就不必修复此问题。 [MetadataType(typeof(MetaData))] public partial class Tour public class MetaData [ForeignKey(nameof(TourCategory))] public virtual TourCategory TourCategory get; set; 【参考方案14】:

对我来说(使用 Visual Studio 2017 和 Entity Framework 6.1.3 下的数据库优先模型),重新启动 Visual Studio 并重建后问题就消失了。

【讨论】:

这看起来不是问题的明确答案,因为您没有解释原因。它应该作为评论。【参考方案15】:

在我的例子中,我错误地定义了一个由两个外键组成的主键,如下所示:

HasKey(x => x.FooId);
HasKey(x => x.BarId);

HasRequired(x => x.Foo)
    .WithMany(y => y.Foos);
HasRequired(x => x.Bar);

我得到的错误是“无效的列名 Bar_ID”。

正确指定复合主键解决了问题:

HasKey(x => new  x.FooId, x.BarId );

...

【讨论】:

【参考方案16】:

如果你对同一个表有多次外键引用,那么你可以使用 InverseProperty

这样的——

[InverseProperty("MyID1")]
public virtual ICollection<MyTable> set1  get; set; 
[InverseProperty("MyID2")]
public virtual ICollection<MyTable> set2  get; set; 

【讨论】:

【参考方案17】:

对我来说,问题是我在我的应用程序中映射了两次表 - 一次通过代码优先,一次通过数据库优先。

删除任何一个都可以解决我的问题。

【讨论】:

【参考方案18】:

我也遇到了这个问题,似乎有几个不同的原因。对我来说,它在包含导航对象的父类中有一个 id 属性错误地定义为 int 而不是 long。数据库中的 id 字段被定义为 bigint,对应于 C# 中的 long。这不会导致编译时错误,但会导致与 OP 相同的运行时错误:

// Domain model parent object
public class WidgetConfig 

    public WidgetConfig(long id, int stateId, long? widgetId)
    
        Id = id;
        StateId = stateId;
        WidgetId = widgetId;
    

    private WidgetConfig()
    
    

    public long Id  get; set; 

    public int StateId  get; set; 

    // Ensure this type is correct
    public long? WidgetId  get; set;  

    public virtual Widget Widget  get; set; 


// Domain model object
public class Widget

    public Widget(long id, string name, string description)
    
        Id = id;
        Name = name;
        Description = description;
    

    private Widget()
    
    

    public long Id  get; set; 

    public string Name  get; set; 

    public string Description  get; set; 


// EF mapping
public class WidgetConfigMap : EntityTypeConfiguration<WidgetConfig>

    public WidgetConfigMap()
    
        HasKey(x => x.Id);
        ToTable(nameof(WidgetConfig));
        Property(x => x.Id).HasColumnName(nameof(WidgetConfig.Id)).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
        Property(x => x.StateId).HasColumnName(nameof(WidgetConfig.StateId));
        Property(x => x.WidgetId).HasColumnName(nameof(WidgetConfig.WidgetId));
    
   

// Service
public class WidgetsService : ServiceBase, IWidgetsService

    private IWidgetsRepository _repository;

    public WidgetsService(IWidgetsRepository repository)
    
        _repository = repository;
    

    public List<WidgetConfig> ListWithDetails()
    
        var list = _repository.ListWithDetails();

        return new WidgetConfigMapping().ConvertModelListToDtoList(list).ToList();
    
   

// Repository
public class WidgetsRepository: BaseRepository<WidgetConfig, long>, IWidgetsRepository

    public WidgetsRepository(Context context)
        : base(context, id => widget => widget.Id == id)
    
    

    public IEnumerable<WidgetConfig> ListWithDetails()
    
        var widgets = Query
            .Include(x => x.State)
            .Include(x => x.Widget);

        return widgets;
    

【讨论】:

【参考方案19】:

检查您是否有任何 ICollections。

我发现当您有一个引用表的 ICollection 并且没有它可以计算的列时,它会为您创建一个以尝试在表之间建立连接。这特别发生在 ICollection 上,让我“笨拙”地试图弄清楚。

【讨论】:

只是为了明确这个答案,因为它最适合我的情况(但直到我弄清楚我的问题后我才知道)。如果您在检索 Table 时遇到与 OtherTable_ID 相关的错误,请转到您的 OtherTable 模型并确保其中没有 ICollection。如果没有定义关系,框架将自动假定您必须具有对 OtherTable 的 FK,并在生成的 SQL 中创建这些额外的属性。 EF浪费了我的4个小时@NitinSawant 就这样? EF 每天浪费我 4 个小时来处理所有重复和未附加的记录。@LUKE 你的评论救了我。我非常爱你:)@LUKE 是我们需要的 EF 英雄,而不是我们应得的 EF 英雄。我爱你。

以上是关于实体框架 - 列名“*_ID”无效的主要内容,如果未能解决你的问题,请参考以下文章

实体框架核心:无效的列名“UserId1”

在实体框架.net核心中获取无效的列名“CompanyLocationId”

实体框架 - 无效的列名称'* _ID“

实体框架创建列名比预期长的数据库

实体框架代码优先自加入,'多重性在角色中无效'

扩展MVC5和实体框架6 ApplicationUser导致用户注册无效列错误