【问题标题】:Entity Framework - Invalid Column Name '*_ID"实体框架 - 列名“*_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; }
  • 请标记答案

标签: c# .net entity-framework-4


【解决方案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 英雄。我爱你。
                              猜你喜欢
                              • 1970-01-01
                              • 2018-05-07
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2014-08-28
                              • 2012-08-24
                              相关资源
                              最近更新 更多