2

EF Code first 4.1 の使用に問題があり、おそらく何かを理解していません。

私の理解では、リレーションシップ (コレクションまたは単一のオブジェクト) を仮想としてマークすることで、オンデマンドで遅延ロードされるため、次のようなことができます。

var page = context.Pages.Where(xxxx);

var department = page.Department; //load this on demand?
var name = department.Name; //null reference exception

ただし、page.DepartmentId は正しく設定されています。さらに、 context.Entry(page).Reference(p => p.Department).Load() を使用して参照を手動でロードすることは機能しますが、オブジェクト モデルを持つことの全体的なポイントは、執拗にどこでもそれを行う必要がないことです。

public class Page
{
  public int DepartmentId { get; set; }
  public virtual Department { get; set; }
}

public class Department
{
  public virtual ICollection<Page> Pages { get; set; }
}

コンテキスト OnModelCreating

 modelBuilder.Entity<Page>().HasRequired(x => x.Department).WithMany(y => y.Pages).HasForeignKey(x => x.DepartmentId).WillCascadeOnDelete(false);

もちろん、遅延読み込みを無効にしていません。

4

3 に答える 3

4

プロジェクトのどこかに問題がある可能性があります。あなたの作品に基づいて簡単なアプリケーションを作成しましたが、すべて正常に動作します。試してみて、何が違うのか見てみましょう。

まず、私の単純なコンテキスト:

class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Page>().HasRequired(x => x.Department).WithMany(y => y.Pages).HasForeignKey(x => x.DepartmentId).WillCascadeOnDelete(false);
    }

    public IDbSet<Page> Pages { get; set; }
    public IDbSet<Department> Departments { get; set; }
}

いくつかのデータをデータベースに入れるためのほとんどダミーの初期化子:

class TestInit : DropCreateDatabaseAlways<MyContext>
{
    protected override void Seed(MyContext context)
    {
        base.Seed(context);

        var newDepartment = context.Departments.Create();
        newDepartment.Name = "test";
        context.Departments.Add(newDepartment);

        var newPage = context.Pages.Create();
        newPage.Department = newDepartment;
        context.Pages.Add(newPage);

        context.SaveChanges();

        // leaving nothing in context
        var fullContext = (context as IObjectContextAdapter).ObjectContext;
        fullContext.Detach(newDepartment);
        fullContext.Detach(newPage);
    }
}

そしてあなたのクラス:

public class Page
{
    public int ID { get; set; }
    public int DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

public class Department
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Page> Pages { get; set; }
}

今度はテスト: Database.SetInitializer(new TestInit());

using (MyContext context = new MyContext())
{
    Console.WriteLine(context.Pages.Local.Count);
    Console.WriteLine(context.Departments.Local.Count);

    var page = context.Pages.First();
    Console.WriteLine(page.GetType().FullName);
    Console.WriteLine(page.Department.Name);
}

表示されるはずです (プロキシ ハッシュはおそらく少し異なります)。

0
0
System.Data.Entity.DynamicProxies.Page_6D31E91F3B1E767826A19855D3A934B59F85AC161548E4761283C85824520E1D
test

最初の 2 つのゼロは、コンテキスト内にエンティティがないことを確認するためにあります。Page クラスの型はプロキシである必要があります。それがプログラム自体の型である場合、プロキシは生成されていません。おそらく電源がオフになっているか、何かが仮想ではないなどです。最後の行は実際の部門の名前です。

プログラムを実行すると、他のクエリに加えて、次のことも行われます。

SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[Name] AS [Name]
FROM [dbo].[Departments] AS [Extent1]
WHERE [Extent1].[ID] = @EntityKeyValue1

データベースに送信されます。

于 2012-01-07T08:05:17.673 に答える
1

私は自分の状況で何が間違っていたのかを理解しました。デフォルトのコンストラクターをプライベートとしてマークしたので、ef はプロキシーを生成しませんでした。

みんな、ありがとう。

于 2012-01-07T16:29:58.880 に答える
0

Page の次のモデルを試して、それが役立つかどうかを確認してください

public class Page
{
    public int DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

部門の変数がありません。今すぐうまくいくことを願っています

于 2012-01-07T08:12:53.040 に答える