C# 实体框架-列名无效'*_ID";

C# 实体框架-列名无效'*_ID";,c#,.net,entity-framework-4,C#,.net,Entity Framework 4,我已经将这个问题缩小到代码优先和数据库优先EF之间的一些问题,但我不确定如何修复它。我会尽量说清楚,但老实说,我自己也在这里失去了一些理解。这是实体框架4.4 我继承了一个使用实体框架的项目,但是许多实际的文件被删除了,没有真正的方法返回。我重新添加了EF(数据库优先)并复制了T4设置,该项目就是围绕它构建的。它生成了所有数据库模型的代码版本和一个DBContext代码文件 如果我的连接字符串看起来像“normal”.NET连接字符串,我会得到一个关于无效列名“ProcessState_ID”不

我已经将这个问题缩小到代码优先和数据库优先EF之间的一些问题,但我不确定如何修复它。我会尽量说清楚,但老实说,我自己也在这里失去了一些理解。这是实体框架4.4

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

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

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

现在,在尝试将前面的代码与实体框架匹配时,我希望保留“normal”.NET连接字符串

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

检查是否有ICollections


我发现,当你有一个ICollection引用一个表,而没有一个列是它能找到的,它会创建一个,让你尝试在表之间建立连接。这种情况在ICollection中特别发生,并促使我“疯狂”地试图找出答案。

我终于找到了答案

我首先做的是EF6数据库,我想知道“扩展未知列”错误——出于某种原因,它生成了表名下划线列名,并试图找到一个不存在的列

在我的例子中,我的一个表有两个外键引用,指向另一个表中的同一主键-类似于这样:

Animals            Owners
=======            ======
AnimalID (PK)      Pet1ID    <- FK to AnimalID
                   Pet2ID    <- also FK to AnimalID
public class OwnerConfiguration : EntityTypeConfiguration<Owner>
{
    public OwnerConfiguration()
    {
        HasRequired(x => x.Animals)
            .WithMany(x => x.Owners)  // Or, just .WithMany()
            .HasForeignKey(x => x.Pet1ID);
    }
}
HasKey(x => x.FooId);
HasKey(x => x.BarId);

HasRequired(x => x.Foo)
    .WithMany(y => y.Foos);
HasRequired(x => x.Bar);
A.HasOptional(p=> p.NavigationToBProperty).WithMany().HasForeignKey(key => key.BId);
有了这一点,EF将(也许)开始像你期望的那样工作。轰

此外,如果将上述内容与可为空的列一起使用,也会出现相同的错误-只需使用
.hasportional()
而不是
.hasprequired()


这里有一个链接让我越过了驼峰:

然后,Fluent API文档提供了帮助,特别是外键示例:

您还可以将配置放在密钥的另一端,如下所述:


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

对于那些(像我一样)没有立即理解其他两个答案的人来说,这是一个迟到的条目

所以

EF正在尝试从父表KEY-REFERENCE映射到期望的名称…并且由于…外键名称在数据库子表关系中被“更改或缩短”…您将收到上面的消息

(此修复程序在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; }
}

我也有这个问题,似乎有几个不同的原因。对我来说,它在包含导航对象的父类中错误地将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;
    }
}
//域模型父对象
公共类WidgetConfig
{
公共WidgetConfig(长id、int stateId、长?widgetId)
{
Id=Id;
StateId=StateId;
WidgetId=WidgetId;
}
私有WidgetConfig()
{
}
公共长Id{get;set;}
public int StateId{get;set;}
//确保此类型正确
public long?WidgetId{get;set;}
公共虚拟小部件{get;set;}
}
//域模型对象
公共类小部件
{
公共小部件(长id、字符串名称、字符串描述)
{
Id=Id;
名称=名称;
描述=描述;
}
私有Widget()
{
}
公共长Id{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
}
//EF映射
公共类WidgetConfigMap:EntityTypeConfiguration
{
公共WidgetConfigMap()
{
HasKey(x=>x.Id);
ToTable(nameof(WidgetConfig));
属性(x=>x.Id).HasColumnName(nameof(WidgetConfig.Id)).hasDatabaseGenerateOption(DatabaseGenerateOption.Identity).IsRequired();
属性(x=>x.StateId).HasColumnName(nameof(WidgetConfig.StateId));
属性(x=>x.WidgetId).HasColumnName(nameof(WidgetConfig.WidgetId));
}
}   
//服务
公共类WidgetsService:ServiceBase,IWidgetsService
{
私人IWidgetsRepository存储库;
公共WidgetsService(IWidgetsRepository存储库)
{
_存储库=存储库;
}
公共列表WithDetails()
{
var list=_repository.ListWithDetails();
返回新的WidgetConfigMapping().ConvertModelListToList(列表).ToList();
}
}   
//存储库
公共类WidgetsRepository:BaseRepository,IWidgetsRepository
{
公共WidgetsRepository(上下文)
:base(上下文,id=>widget=>widget.id==id)
{
}
公共IEnumerable列表WithDetails()
{
var=Query
.Include(x=>x.State)
.包括(x=>x.Widget);
返回窗口小部件;
}
}

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


在我的案例中,删除任何一个都可以解决问题。

假设:

  • 表格
  • OtherTable
  • OtherTable\u ID
现在选择以下方式之一:


(A) <
HasKey(x => new { x.FooId, x.BarId });

...
public class A 
{
    …
    public int? BId {get; set;}
    public B NavigationToBProperty {get; set;}
}
public class B
{
    …
    public List<A> ListOfAProperty {get; set;}
}
A.HasOptional(p=> p.NavigationToBProperty).WithMany().HasForeignKey(key => key.BId);
db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
A.HasOptional(p=> p.NavigationToBProperty).WithMany(x => x.ListOfAProperty).HasForeignKey(key => key.BId);
Table : PERSON
Id
AncestorId (with a foreign key which references Id named Parent) 
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