118

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

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

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

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

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

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

4

19 回答 19

114

检查您是否有任何 ICollections。

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

于 2013-12-18T08:23:05.403 回答
75

对于那些(像我一样)没有立即理解其他 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; }
}
于 2015-07-11T23:52:51.897 回答
45

我终于想通了。

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

我现在遇到了一些新问题,但这是缺失的巨大概念差距。希望能帮助到你!

于 2015-01-17T16:38:22.920 回答
19

假设:

  • Table
  • OtherTable
  • OtherTable_ID

现在选择其中一种方式:


一个)

消除ICollection<Table>

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

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


二)

  • 添加OtherTableIdTable

  • OtherTableIdTablein数据库中定义
于 2017-05-05T19:57:52.007 回答
3

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

于 2019-06-10T04:39:28.513 回答
3

对我来说,这种行为的原因是因为使用 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 Output->Debug 窗口

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);
于 2018-11-03T23:17:34.143 回答
3

就我而言,我错误地定义了一个由两个外键组成的主键,如下所示:

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

...
于 2017-08-02T18:42:46.133 回答
2

我也有这个问题,似乎有几个不同的原因。对我来说,它在包含导航对象的父类中有一个 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;
    }
}
于 2016-03-22T11:59:50.157 回答
2

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

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

于 2017-03-14T18:31:50.680 回答
1

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

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

[ForeignKey("PrestadorId")] 公共虚拟 AwmPrestadoresServicios Colaboradores { get; 放; }

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

于 2020-03-28T01:58:52.000 回答
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
于 2021-05-13T18:41:00.900 回答
1

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

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

于 2020-01-21T04:31:59.737 回答
0

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

于 2021-02-28T00:07:08.573 回答
0

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

例如 :

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

你将不得不改变AncestorIdPersonId

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

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

于 2020-07-23T09:15:30.757 回答
0

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

像这样的东西-

[InverseProperty("MyID1")]
public virtual ICollection<MyTable> set1 { get; set; }
[InverseProperty("MyID2")]
public virtual ICollection<MyTable> set2 { get; set; }
于 2017-07-20T21:01:35.100 回答
0

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

于 2018-11-20T15:20:27.007 回答
0

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

public Guid GroupId { get; set; }
public Group Group { get; set; }

->

public Guid GroupId { get; set; }
public virtual Group Group { get; set; }
于 2021-11-12T08:03:14.653 回答
0

如果您的表没有任何一对多关系,那么我的问题就结束了,因为我有一个 MS SQL 触发器引用了一个旧的/不存在的列。

于 2021-11-04T14:39:20.533 回答
0

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

于 2017-09-28T04:49:09.533 回答