web-dev-qa-db-ja.com

Entity Framework-無効な列名「* _ID」

これをCode FirstとDatabase First EFの間の問題に絞りましたが、修正方法がわかりません。できる限り明確にしようとしますが、正直なところ、ここで自分自身の理解の一部を逃しています。これはEntity Framework 4.4です

Entity Frameworkを使用したプロジェクトを継承しましたが、実際のファイルの多くは削除され、実際に戻る方法はありませんでした。 EF(データベースを最初に)を再度追加し、プロジェクトが構築されたT4セットアップを複製しました。すべてのデータベースモデルのコードバージョンとDBContextコードファイルを生成しました。

接続文字列が「通常の」.NET接続文字列のように見える場合、無効な列名「ProcessState_ID」が存在しないというエラーが表示されます。 ProcessState_IDはコードベースにはまったくありません。EDMXファイルなどにはありません。これは、クエリ内の一部の自動EF変換のようです。

接続文字列をEntity Frameworkモデルと一致させると、正常に機能します。

ここで、以前のコードをEntity Frameworkに一致させようとして、「通常の」.NET接続文字列を保持したいと思います。

したがって、ここで2つの質問があります。1.コードで通常の接続文字列からEF接続文字列に移動する良い方法は何ですか? 2.ここに、無効な列名エラーを停止するように見えない別の修正がありますか?

75

ICollectionがあるかどうかを確認します。

私が理解したのは、テーブルを参照するICollectionがあり、それを把握できる列がない場合、テーブル間を接続しようとする列が作成されることです。これは特にICollectionで発生し、それを理解しようとして「バティー」に追い込まれました。

73
drewid

これは、他の2つの答えをすぐに理解しなかった人(私のような人)にとっては遅刻です。

そう...

EFは、親テーブルのキー参照から期待される名前にマップしようとしています...以来、外部キー名は、データベースの子テーブル関係で「変更または短縮」されました...上記のメッセージが表示されます。

(この修正は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; }
}
46
Prisoner ZERO

聖なる牛-何時間も試した後、私はついにこれを理解しました。

私は最初にEF6データベースを実行していますが、「extent unknown column」エラーについて疑問に思っていました-何らかの理由でテーブル名アンダースコア列名を生成し、存在しない列を見つけようとしました。

私の場合、私のテーブルの1つに、別のテーブルの同じ主キーへの2つの外部キー参照がありました。次のようなものです。

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は(おそらく)期待どおりに動作し始めます。ブーム。

また、null許容列で上記を使用すると、同じエラーが発生します-.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

私が今直面しているいくつかの新しい問題がありますが、それは欠落していた大きな概念上のギャップでした。それが役に立てば幸い!

34
Ben

仮定:

  • Table
  • OtherTable
  • OtherTable_ID

次のいずれかの方法を選択します。


A)

ICollection<Table>を削除

Tableを取得するときにOtherTable_IDに関連するエラーが発生した場合は、OtherTableモデルに移動して、そこにICollection<Table>がないことを確認してください。関係が定義されていない場合、フレームワークは、OtherTableに対するFKが必要であると自動的に想定し、生成されたSQLでこれらの追加のプロパティを作成します。

この回答のクレジットはすべて@LUKEに属します。上記の回答は、@ drewid回答の下の彼のコメントです。彼のコメントはとてもきれいだと思うので、答えとして書き直しました。


B)

  • OtherTableIdTableに追加

そして

  • データベースのOtherTableIdTableを定義
11
RAM

私の場合、次のような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 });

...
2
Seth

私にとっての問題は、アプリでテーブルを2回マップしたことです-1回はCode First、もう1回はDatabase Firstです。

いずれかを削除すると、私の場合の問題は解決します。

1
Renan

私にとって、この動作の原因は、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つのリレーションがありました-> 1つは正しいIDで、もう1つはA_Id

問題の問題は、このB.List<A>ナビゲーションプロパティをマッピングに追加しなかったことです。

だからこれは私の場合、正しいマッピングがどのようになければならなかったかです:

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

私もこの問題を抱えていましたが、いくつかの異なる原因があるようです。私にとっては、ナビゲーションオブジェクトを含む親クラスで、idプロパティがlongではなくintとして誤って定義されていました。データベースのidフィールドは、C#のlongに対応するbigintとして定義されました。これによりコンパイル時エラーは発生しませんでしたが、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;
    }
}
1
Ciaran Bruen

私の場合、この問題の原因は、移行されたデータベースに存在しないFOREIGN KEY制約でした。そのため、既存の仮想ICollectionは正常にロードされませんでした。

0
Stefan Michev

同じテーブルへの外部キー参照が複数回ある場合は、InversePropertyを使用できます

このようなもの-

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

私の場合、シードメソッドデータは、以前の移行で削除されたテーブル列をまだ呼び出していました。 Automapperを使用している場合は、マッピングを再確認してください。

0
SauerTrout

私にとって(Visual Studio 2017とEntity Framework 6.1.3のデータベース優先モデルを使用)、Visual Studioを再起動して再構築すると問題はなくなりました。

0
neuronz