私はEntityFrameworkを初めて使用し、CodeFirstを使用してデータベースからエンティティをロードする方法を学習しようとしています。
私のモデルにはユーザーが含まれています:
public class User
{
public int UserID { get; set; }
[Required]
public string Name { get; set; }
// Navigation Properties
public virtual ICollection<AuditEntry> AuditEntries { get; set; }
}
各ユーザーは、それぞれに簡単なメッセージを含む一連の監査エントリを持つことができます。
public class AuditEntry
{
public int AuditEntryID { get; set; }
[Required]
public string Message { get; set; }
// Navigation Properties
public int UserID { get; set; }
public virtual User User { get; set; }
}
2つのテーブルを公開するだけのDBContextがあります。
public DbSet<User> Users { get; set; }
public DbSet<AuditEntry> AuditEntries { get; set; }
私がやりたいのは、メッセージを含むAuditEntryオブジェクトのリストと、UserIDおよびNameプロパティを含む関連するUserオブジェクトをロードすることです。
List<AuditEntry> auditEntries = db.AuditEntries.ToList();
ナビゲーションプロパティを仮想としてマークし、遅延読み込みを無効にしていないため、無限に深いオブジェクトグラフが表示されます(各AuditEntryにはAuditEntriesのリストを含むUserオブジェクトがあり、各オブジェクトにはUserオブジェクトが含まれています。 AuditEntriesなどのリストが含まれています)
オブジェクトをシリアル化する場合(たとえば、結果としてWeb APIで送信する場合)、これは適切ではありません。
遅延読み込みをオフにしてみました(モデルのナビゲーションプロパティから仮想キーワードを削除するか、this.Configuration.LazyLoadingEnabled = false;をDBContextに追加します)。予想どおり、これにより、Userがnullに設定されたAuditEntryオブジェクトのフラットリストが作成されます。
遅延読み込みをオフにして、次のようにユーザーの読み込みを熱心に試みました。
var auditentries = db.AuditEntries.Include(a => a.User);
しかし、これは以前と同じ深い/周期的な結果になります。
後方参照をロードしたり、ナビゲーションプロパティを元のオブジェクトに戻したり、サイクルを作成したりせずに、1レベルの深さ(たとえば、ユーザーのIDと名前を含める)をロードするにはどうすればよいですか?