130

Entity Frameworkm を使用してデータを入力しようとしていGridViewますが、毎回次のエラーが発生します。

「オブジェクト 'COSIS_DAL.MemberLoan' のプロパティ アクセサー 'LoanProduct' が次の例外をスローしました: ObjectContext インスタンスは破棄されており、接続を必要とする操作には使用できなくなりました。」

私のコードは次のとおりです。

public List<MemberLoan> GetAllMembersForLoan(string keyword)
{
    using (CosisEntities db = new CosisEntities())
    {
        IQueryable<MemberLoan> query = db.MemberLoans.OrderByDescending(m => m.LoanDate);
        if (!string.IsNullOrEmpty(keyword))
        {
            keyword = keyword.ToLower();
            query = query.Where(m =>
                  m.LoanProviderCode.Contains(keyword)
                  || m.MemNo.Contains(keyword)
                  || (!string.IsNullOrEmpty(m.LoanProduct.LoanProductName) && m.LoanProduct.LoanProductName.ToLower().Contains(keyword))
                  || m.Membership.MemName.Contains(keyword)
                  || m.GeneralMasterInformation.Description.Contains(keyword)

                  );
        }
        return query.ToList();
    }
}


protected void btnSearch_Click(object sender, ImageClickEventArgs e)
{
    string keyword = txtKeyword.Text.ToLower();
    LoanController c = new LoanController();
    List<COSIS_DAL.MemberLoan> list = new List<COSIS_DAL.MemberLoan>();
    list = c.GetAllMembersForLoan(keyword);

    if (list.Count <= 0)
    {
        lblMsg.Text = "No Records Found";
        GridView1.DataSourceID = null;
        GridView1.DataSource = null;
        GridView1.DataBind();
    }
    else
    {
        lblMsg.Text = "";
        GridView1.DataSourceID = null;   
        GridView1.DataSource = list;
        GridView1.DataBind();
    }
}

LoanProductNameエラーは、の列に言及していますGridview。言及: バックエンド DB として C#、ASP.net、SQL-Server 2008 を使用しています。

私はEntity Frameworkを初めて使用します。なぜこのエラーが発生するのか理解できません。誰でも私を助けてもらえますか?

4

8 に答える 8

27

結論

コードは、遅延読み込みが有効になっているエンティティ フレームワークを介してデータ (エンティティ) を取得しました。DbContext が破棄された後、コードは明示的に要求されていないプロパティ (関連/関係/ナビゲーション エンティティ) を参照しています。

すなわち

このInvalidOperationExceptionメッセージの は常に同じことを意味します。DbContext が破棄された後、エンティティ フレームワークからデータ (エンティティ) を要求しています。

簡単なケース:

(これらのクラスは、この回答のすべての例で使用され、すべてのナビゲーション プロパティが正しく構成され、データベースにテーブルが関連付けられていることを前提としています)

public class Person
{
  public int Id { get; set; }
  public string name { get; set; }
  public int? PetId { get; set; }
  public Pet Pet { get; set; }
}

public class Pet 
{
  public string name { get; set; }
}

using (var db = new dbContext())
{
  var person = db.Persons.FirstOrDefaultAsync(p => p.id == 1);
}

Console.WriteLine(person.Pet.Name);

InvalidOperationExceptiondbContext が遅延読み込みを無効にしておらず、コードが using ステートメントによって Context が破棄された後に Pet ナビゲーション プロパティにアクセスしているため、最後の行は をスローします。

デバッグ

この例外の原因をどのように見つけますか? 発生した場所に正確にスローされる例外自体を確認することとは別に、Visual Studio でのデバッグの一般的なルールが適用されます。戦略的なブレークポイントを配置し、変数を調べます。 Quick)Watch ウィンドウまたは Locals や Autos などのさまざまなデバッグ パネルを使用します。

参照がどこに設定されているか、または設定されていないかを確認するには、その名前を右クリックして [すべての参照を検索] を選択します。その後、データを要求するすべての場所にブレークポイントを配置し、デバッガーを接続してプログラムを実行できます。デバッガーがこのようなブレークポイントで中断するたびに、ナビゲーション プロパティが設定されている必要があるかどうか、または要求されたデータが必要かどうかを判断する必要があります。

回避する方法

遅延読み込みを無効にする

public class MyDbContext : DbContext
{
  public MyDbContext()
  {
    this.Configuration.LazyLoadingEnabled = false;
  }
}

長所: InvalidOperationException をスローする代わりに、プロパティは null になります。null のプロパティにアクセスするか、このプロパティのプロパティを変更しようとすると、NullReferenceExceptionがスローされます。

必要に応じてオブジェクトを明示的にリクエストする方法:

using (var db = new dbContext())
{
  var person = db.Persons
    .Include(p => p.Pet)
    .FirstOrDefaultAsync(p => p.id == 1);
}
Console.WriteLine(person.Pet.Name);  // No Exception Thrown

前の例では、Entity Framework は Person に加えて Pet を実体化します。これは、データベースへの単一の呼び出しであるため、有利な場合があります。(ただし、返される結果の数と要求されたナビゲーション プロパティの数によっては、大きなパフォーマンスの問題が発生する可能性もあります。この場合、両方のインスタンスが 1 つのレコードと 1 つの結合のみであるため、パフォーマンスの低下はありません)。

また

using (var db = new dbContext())
{
  var person = db.Persons.FirstOrDefaultAsync(p => p.id == 1);

  var pet = db.Pets.FirstOrDefaultAsync(p => p.id == person.PetId);
}
Console.WriteLine(person.Pet.Name);  // No Exception Thrown

前の例では、Entity Framework は、データベースに追加の呼び出しを行うことで、Person とは別に Pet を実体化します。既定では、Entity Framework はデータベースから取得したオブジェクトを追跡し、一致するナビゲーション プロパティが見つかった場合は、これらのエンティティを魔法のように自動的に設定します。この場合PetIdPersonオブジェクトの が と一致するため、値が pet 変数に割り当てられる前にPet.Id、Entity Framework は取得Person.PetしたPet値に を割り当てます。

コードがいつ、どのように Entity Framework を介してデータを要求するかをプログラマーに理解させるため、私は常にこのアプローチをお勧めします。コードがエンティティのプロパティで null 参照例外をスローした場合、ほとんどの場合、そのデータを明示的に要求していないことを確認できます。

于 2017-10-25T17:01:46.287 に答える
-3

になり得る

 -> context.Configuration.ProxyCreationEnabled = false;

using (var context = new BDPuntoDeVenta())
            {
                context.Configuration.ProxyCreationEnabled = false;
                return context.FacturaDetalle.Where(x => x.ID_Factura == _ID_Factura && x.Devuelto != true).ToList();
            }
于 2021-03-04T11:57:41.153 に答える