实体框架 - 列名“*_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_AnimalID1
和 Owners_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 => item.LogicalShipment).WithMany(s => s.Items).HasForeignKey(item => item.LogicalShipmentId).IsRequired();
我遇到了一个与此非常相似的问题。在我的例子中,TableA 有一个指向 TableB 的外键,而 TableB 有 Listthis.HasRequired( x => x.TableB ).WithMany( x => x.TableA ).HasForeignKey( x => x.TableBId ).WillCascadeOnDelete( true );
非常感谢!如果您在同一张表上的导航属性存在此问题,则必须更改我们属性的名称。
例如:
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<A>
,所以我有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<A>
导航属性添加到映射中。
所以在我的情况下,正确的映射必须是这样的:
A.HasOptional(p=> p.NavigationToBProperty).WithMany(x => x.ListOfAProperty).HasForeignKey(key => key.BId);
【讨论】:
【参考方案12】:假设:
Table
OtherTable
OtherTable_ID
现在选择以下方式之一:
A)
删除ICollection<Table>
如果您在检索Table
时遇到与OtherTable_ID
相关的错误,请转到您的OtherTable
模型并确保其中没有ICollection<Table>
。如果没有定义关系,框架将自动假定您必须具有对 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以上是关于实体框架 - 列名“*_ID”无效的主要内容,如果未能解决你的问题,请参考以下文章