实体框架 - 无效的列名称'* _ID“
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实体框架 - 无效的列名称'* _ID“相关的知识,希望对你有一定的参考价值。
我把这缩小到Code First和Database first EF之间的一些问题,但我不确定如何修复它。我会尽量保持清醒,但老实说,我自己也缺少一些理解。这是实体框架4.4
我继承了一个使用Entity Framework的项目,但许多实际文件都被删除了,没有真正的方法可以返回。我重新添加了EF(数据库优先)并复制了项目所围绕的T4设置。它生成了所有数据库模型的代码版本和DBContext代码文件。
如果我的连接字符串看起来像一个“正常”的.NET连接字符串,我得到一个关于无效列的错误名称“ProcessState_ID”不存在。 ProcessState_ID根本不在代码库中,它不在EDMX文件或任何内容中。这似乎是查询中的一些自动EF转换。
当我使连接字符串与实体框架模型匹配时,它工作正常。
现在尝试将以前的代码与实体框架相匹配,我想保留“正常”的.NET连接字符串。
所以我在这里有两个问题:1。在代码中从普通连接字符串到EF连接字符串的好方法是什么? 2.这里有另一个修复,我没有看到停止无效的列名错误?
检查您是否有任何ICollections。
我想到的是当你有一个引用一个表的ICollection并且它没有可以找到的列时,它会创建一个让你尝试在表之间建立连接。这种情况恰好发生在ICollection上并且让我“慌乱”试图解决这个问题。
对我来说(使用Visual Studio 2017和Entity Framework 6.1.3下的数据库优先模型),重新启动Visual Studio和重建后问题就消失了。
就我而言,我的种子方法数据仍在调用一个表列,该列已在先前的迁移中被删除。如果您使用的是Automapper,请仔细检查映射。
在我的情况下,此问题的原因是迁移的数据库上缺少FOREIGN KEY约束。因此,未成功加载现有的虚拟ICollection。
对于那些没有立即理解其他2个答案的人(像我一样),这是一个迟到的条目。
所以...
EF正试图从PARENT TABLES KEY-REFERENCE映射到EXPECTED名称...并且因为...... FOREARIGN KEY名称在数据库CHILD TABLE关系中被“更改或缩短”...您将收到上面的消息。
(此修复版本可能因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; }
}
神圣的牛 - 经过几个小时的尝试,我终于弄明白了。
我首先在做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()
。
这是让我超越驼峰的链接:
然后,Fluent API文档提供帮助,尤其是外键示例:
http://msdn.microsoft.com/en-us/data/jj591620.aspx
您也可以将配置放在密钥的另一端,如下所述:
我现在遇到了一些新问题,但这是一个巨大的概念缺口。希望能帮助到你!
假设:
Table
OtherTable
OtherTable_ID
现在选择以下方法之一:
一个)
删除ICollection<Table>
如果你在检索OtherTable_ID
时有一些与Table
相关的错误,请转到你的OtherTable
模型并确保你没有ICollection<Table>
。如果没有定义关系,框架将自动假定您必须具有到OtherTable的FK并在生成的SQL中创建这些额外属性。
此答案的所有信用均归@LUKE所有。上面的答案是他在@drewid回答下的评论。我认为他的评论是如此简洁,然后我把它改写成答案。
B)
- 将
OtherTableId
添加到Table
和
- 在数据库中的
OtherTableId
中定义Table
在我的情况下,我错误地定义了一个由两个外键组成的主键,如下所示:
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 });
...
我也有这个问题,似乎有几个不同的原因。对我来说,在包含导航对象的父类中错误地将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;
}
}
对我来说问题是我在我的应用程序中映射了两次表 - 一次通过Code First,一次通过Database First。
删除任何一个解决了我的问题。
对我来说,这种行为的原因是由于使用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;}
}
我用流利的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 Output-> Debug窗口
db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
生成的SQL有两个来自B表的关系 - >一个具有正确的id,另一个具有A_Id
以上是关于实体框架 - 无效的列名称'* _ID“的主要内容,如果未能解决你的问题,请参考以下文章
AspNetUser 上的实体框架流利的 api 1:1 属性无法更改 Account_Id 属性
在实体框架.net核心中获取无效的列名“CompanyLocationId”
扩展MVC5和实体框架6 ApplicationUser导致用户注册无效列错误
无效的语言环境名称 Chinese (Simplified)_People''s Republic of China.936