最初にコードを使用している既存のデータベースがあります。必要な場所に外部キーがあることを確認するために、SQL データベースのテーブルをクリーンアップしました。Entity_Company というテーブルを指す ClientID という null 許容の外部キーを持つ Inventory_Base というテーブルが 1 つあります。Inventory_Base は ComputerEntity というエンティティ オブジェクトにマップされ、Entity_Company は CompanyEntity というエンティティ オブジェクトにマップされます。ナビゲーションの小道具は正しく設定されていると思いますが、間違っていたら教えてください。私が抱えている問題は、CompanyEntity ナビゲーション プロパティが読み込まれないことです。ComputerEntity オブジェクトの ClientID の値を確認できるように、両方のナビゲーション プロパティを削除しようとしましたが、その列がデータベースに存在するにもかかわらず読み込まれません! 私は、EF 規約が「ID」という単語を見ているのではないかと疑っています。
私は自分の ComputerEntity をそのように定義しており、CompanyEntity をロードする必要があります。
[Table("Inventory_Base")]
public class ComputerEntity
{
// primary key
[Key]
public int AssetID { get; set; }
// foreign keys
[ForeignKey("CompanyEntity")]
public int? ClientID { get; set; }
// navigation props
[ForeignKey("ClientID")]
public virtual CompanyEntity CompanyEntity { get; set; }
// these props are fine without custom mapping
public string Hostname { get; set; }
public string ServiceTag { get; set; }
}
これは決してロードされない私の伝説的な CompanyEntity です。
[Table("Entity_Company")]
public class CompanyEntity
{
protected CompanyEntity() {}
// primary key
[Key]
public int ClientID { get; set; }
// foreign key
// nav props
public virtual ICollection<ComputerEntity> ComputerEntities { get; set; }
// regular props
// custom mappings
[Column("CompanyName", TypeName = "nvarchar(MAX)")]
public string Name { get; set; }
[Column("FQDN", TypeName = "nvarchar(MAX)")]
public string Domain { get; set; }
}
ホスト名プロパティが入力と一致し、そのコンピューターが特定の会社に属しているコンピューターを見つけようとしています。クエリを実行している DbSet があり、ナビゲーション プロパティが存在するため、関連する CompanyEntity オブジェクトのプロパティにアクセスできると想定しています。これまでのところ、私は間違っていると想定しており、私の人生では何が問題を引き起こしているのかわかりません。コンピューターを取得しようとしている方法は次のとおりです。
public ComputerEntity FindComputerByHostname(string hostname, string client)
{
var computer = DbSet.Where(x => x.Hostname == hostname && x.CompanyEntity.Name == client).FirstOrDefault(); // <-- always null!
var test = DbSet.Where(x.CompanyEntity.Name == client).ToList() // <-- never finds anything, which is why I suspect a non-working relationship
return computer ;
}
もう 1 つの奇妙さは、ComputerEntity で ClientID を int で null 可能にする必要があることです。そうしないと、ClientID を null にすることはできないという例外が発生します。データベースを見ると、列は null 可能ですが、null 値はありません。変。それがintであるという事実はありますか?何らかの形で関係を壊す?
アップデート
そこで、EF パワー ツールを使用してリバース エンジニアリングを行い、詳細を調べてみました。醜いテーブル名はすべてエンティティとして表示されましたが、これで問題ありません。CompanyEntity は Entity_Company になり、それを参照するすべてのものの ICollection があります。ComputerEntity は Inventory_Base になりましたが、ロードされないという同じ問題があります。謎に追加するために、CompanyEntity (現在は Entity_Company) の他のコレクションは期待どおりにナビゲートします! 自動生成されたマッピング ファイルを確認したところ、破損したコレクションにはすべて、すべてのプロパティに .IsRequired() が含まれています。通常動作するコレクションにはこれがありません。また、壊れたコレクションの ClientID はすべて int ですか? 通常の null 非許容の int ではありません。理由はわかりませんが、これは問題だと思います。企業とそれぞれのコンピューターの間で目前の問題に焦点を当てると、ComputerEntity (現在は Inventory_Base) には恐ろしい int? があります。自動生成されたマッピング ファイルで。SELECT * FROM Inventory_Base WHERE ClientID IS NULL を使用して SQL データベースをチェックしましたが、何も得られませんでした。テーブルを変更して ClientID 列を null 非許容にしようとしましたが、SQL は、テーブルを再作成できないため、変更できないと文句を言います。通常、これはそこにnull値があったことを期待します...しかし、ありません。問題なくうまく機能するエンティティ コレクションに対応する他のテーブルを変更できます。おそらく、問題は破損した SQL テーブルですか? 私はそれが可能だとは思いませんでしたが、誰かがそれをチェックするDBCCコマンドを知っていれば、それは素晴らしいことです. 私の解決策をこの質問と一致させるために、
私が変更したComputerEntityの内部:
[ForeignKey("CompanyEntity")]
public int? ClientID {get;set;}
に:
[ForeignKey("CompanyEntity")]
public int ClientID {get;set;}
テストすると、次の例外が発生します
。ナビゲーション プロパティ 'ClientID' は、タイプ 'ComputerEntity' で宣言されたプロパティではありません。モデルから明示的に除外されていないこと、および有効なナビゲーション プロパティであることを確認してください。
スタック トレース: System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureAssociations (EdmEntityType entityType、EdmModel モデル) で System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure (EdmEntityType entityType、EdmModel モデル) でSystem.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel モデル) System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(EdmModel モデル) System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) で System.Data.Entity.DbModelBuilder.Build (DbConnection providerConnection) で System.Data.Entity.Internal.LazyInternalContext.CreateModel (LazyInternalContext internalContext) で System.Data.Entity.Internal.RetryLazy2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet
1.Initialize() System.Data.Entity.Internal.Linq.InternalSet で1.get_InternalContext()
at System.Data.Entity.Infrastructure.DbQuery
1.System.Linq.IQueryable.get_Provider() で System.Linq.Queryable.FirstOrDefault[TSource](IQueryable 1 source, Expression
1 predicate) で Reporting.Data.InventoryRepository .FindComputerByHostname(String hostname, String client) in c:\Projects\Reporting\Data\Reporting.Data\InventoryRepository.cs:line 22 at Reporting.Services.InventoryService.GetComputerDetails(String hostname, String client) in c:\Projects\ Reporting\Business\Reporting.Services\InventoryService.cs: c:\Projects\Reporting\Tests\Reporting.Services.Tests\InventoryTests.cs の Reporting.Services.Tests.InventoryTests.GetComputerDetailsTest() の行 29:行 39