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

时间:2013-11-13 16:32:57

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

我已将此问题缩小到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.这里是否有另一种解决方法,我没有看到停止无效的列名错误?

17 个答案:

答案 0 :(得分:62)

检查您是否有任何ICollections。

我想到的是当你有一个引用一个表的ICollection并且它没有可以找到的列时,它会创建一个让你尝试在表之间建立连接。这种情况特别发生在ICollection上并且让我“慌乱”试图解决它。

答案 1 :(得分:45)

对于那些没有立即理解其他2个答案的人来说,这是一个迟到的条目。

因此...

EF正试图从PARENT TABLES KEY-REFERENCE映射到EXPECTED名称......并且因为...... FOREIGN 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; }
}

答案 2 :(得分:34)

圣牛 - 经过几个小时的尝试,我终于弄明白了。

我首先在做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

我现在遇到了一些新问题,但这是一个巨大的概念差距。希望它有所帮助!

答案 3 :(得分:8)

<强>假设:

  • Table
  • OtherTable
  • OtherTable_ID

现在选择以下方法之一:

A)

删除ICollection<Table>

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

  

此答案的所有功劳归属于@LUKE。上面的答案是他在@drewid回答下的评论。我认为他的评论是如此简洁,然后我把它改写为答案。

B)

  • OtherTableId添加到Table

  • 在数据库中的OtherTableId
  • 中定义Table

答案 4 :(得分:2)

在我的情况下,我错误地定义了一个由两个外键组成的主键:

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 });

...

答案 5 :(得分:1)

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

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

答案 6 :(得分:1)

对我而言,这是由于EF的多元化问题而发生的。对于以“ -Status”结尾的表,EF认为单数是“ -Statu”。将实体和数据库表名称更改为“ -StatusTypes”即可解决该问题。

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

答案 7 :(得分:1)

对我来说,造成这种现象的原因是因为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调试附加到EF DatabaseContext.Database.Log,以将生成的SQL输出到VS Output-> Debug窗口

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

生成的SQL与B表有2个关系->一个具有正确ID,另一个与A_Id

问题所在是,我没有将此B.List<A>导航属性添加到映射中。

这就是我的情况,正确的映射必须是这样的:

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

答案 8 :(得分:1)

对我来说问题是我在我的应用程序中映射了两次表 - 一次是通过Code First,一次是通过Database First。

删除任何一个解决了我的问题。

答案 9 :(得分:1)

我也有这个问题,似乎有几个不同的原因。对我来说,在包含导航对象的父类中错误地将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;
    }
}

答案 10 :(得分:0)

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

答案 11 :(得分:0)

如果多次对同一个表进行外键引用,则可以使用InverseProperty

像这样的东西 -

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

答案 12 :(得分:0)

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

答案 13 :(得分:0)

就我而言,此问题的原因是在迁移的数据库上缺少FOREIGN KEY约束。因此,现有的虚拟ICollection无法成功加载。

答案 14 :(得分:0)

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

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

[ForeignKey(“ PrestadorId”)] 公共虚拟AwmPrestadoresServicios Colaboradores {get;组; }

也就是说,PRE_ID是PK,但是另一个表中的FK是PRESTADOR_ID,则它起作用。感谢这里的所有评论,我找到了解决方案。 EF的工作方式很神秘。

答案 15 :(得分:0)

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

例如:

$events = self::getCalendarService()->events->listEvents(self::getCalendarService()->calendars->get('primary'), ["showDeleted" => true]);

您必须将Table : PERSON Id AncestorId (with a foreign key which references Id named Parent) 的{​​{1}}更改。

似乎EF试图创建键AncestorId,因为它找不到名为Ancestor的表...

编辑:这是数据库修复程序!

答案 16 :(得分:0)

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