programing

"ObjectContext 인스턴스가 삭제되어 연결이 필요한 작업에 더 이상 사용할 수 없습니다" 문제 해결: InvalidOperation예외.

testmans 2023. 4. 20. 20:09
반응형

"ObjectContext 인스턴스가 삭제되어 연결이 필요한 작업에 더 이상 사용할 수 없습니다" 문제 해결: InvalidOperation예외.

는 를를 a a a a a a a a a a를 채우려고 하고 있다.GridView엔티티 프레임워크를 사용하지만 매번 다음 오류가 발생합니다.

"오브젝트 'COSIS_DAL'의 속성 접근자 'LoanProduct'입니다.MemberLoan'은 다음과 같은 예외를 설정했습니다.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();
    }
}

는 「」를 있습니다.LoanProductNameGridview·로서 Cnet,.DB C#, ASP.net, SQL-Server 2008.

나는 엔티티 프레임워크에 대해 꽤 처음입니다.왜 이런 오류가 발생하는지 이해할 수 없습니다.누가 나 좀 도와줄래?

디폴트로는 엔티티 프레임워크는 네비게이션속성에 lazy-loading을 사용합니다.따라서 이러한 속성은 가상으로 표시되어야 합니다. EF는 엔티티의 프록시 클래스를 생성하고 탐색 속성을 재정의하여 느린 로드를 허용합니다.예: 이 엔티티가 있는 경우:

public class MemberLoan
{
   public string LoandProviderCode { get; set; }
   public virtual Membership Membership { get; set; }
}

엔티티 프레임워크는 나중에 멤버쉽을 느리게 로드할 수 있도록 이 엔티티에서 상속된 프록시를 반환하고 이 프록시에 DbContext 인스턴스를 제공합니다.

public class MemberLoanProxy : MemberLoan
{
    private CosisEntities db;
    private int membershipId;
    private Membership membership;

    public override Membership Membership 
    { 
       get 
       {
          if (membership == null)
              membership = db.Memberships.Find(membershipId);
          return membership;
       }
       set { membership = value; }
    }
}

따라서 엔티티에는 엔티티를 로드하는 데 사용된 DbContext 인스턴스가 있습니다.가지고 있다using코시스 엔티티엔티티가 반환되기 전에 컨텍스트를 폐기합니다.일부 코드가 나중에 느리게 로드된 탐색 속성을 사용하려고 하면 컨텍스트가 그 순간에 삭제되기 때문에 실패합니다.

이 동작을 수정하려면 나중에 필요한 탐색 속성을 빠르게 로드합니다.

IQueryable<MemberLoan> query = db.MemberLoans.Include(m => m.Membership);

그러면 모든 멤버쉽이 프리로드되고 지연 로딩이 사용되지 않습니다.상세한 것에 대하여는, MSDN 의 관련 엔티티 문서를 참조해 주세요.

CosisEntities의 클래스입니다.DbContext using이치노

코드에서는 메서드에서 쿼리 결과를 내보낸 다음 메서드 내에서 컨텍스트를 종료하려고 합니다.결과를 전달한 작업은 그리드 보기를 채우기 위해 도면요소에 액세스하려고 시도합니다.그리드에 바인딩하는 프로세스 중 어딘가에서 느리게 로드된 속성에 액세스하고 있으며 엔티티 프레임워크는 값을 얻기 위해 조회를 수행하려고 합니다.관련 컨텍스트가 이미 종료되었기 때문에 실패합니다.

두 가지 문제가 있습니다.

  1. 그리드에 바인딩할 때 엔티티를 느리게 로드합니다.즉, SQL Server에 대한 쿼리 작업이 많이 수행되고 이로 인해 모든 작업이 느려집니다.기본적으로 관련 속성을 빠르게 로드하도록 설정하거나 확장 방법을 사용하여 Entity Framework에 해당 속성을 이 쿼리 결과에 포함하도록 요청하여 이 문제를 해결할 수 있습니다.

  2. 이 너무 일찍 즉, 문맥이 너무 짧아요.DbContext작업 단위 전체에 걸쳐 사용할 수 있어야 하며, 수중의 작업이 종료되었을 때만 폐기해야 합니다.ASP asp asp 。NET の net net net net net net netHTTP の http http http http 。

결산

코드가 엔티티 프레임워크를 통해 데이터(엔티티)를 취득했으며, 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);

은 '마지막 행'을 던집니다.InvalidOperationException을 디세블로 하지 , dbContext "lazy-loading" 스테이트먼트에 된 후 하고 입니다.

디버깅

이 예외의 원인을 어떻게 찾습니까?Visual Studio의 디버깅에 관한 일반적인 규칙은 예외 자체를 확인하는 것 외에도 다음과 같습니다. 전략적 중단점을 배치하고 변수를 검사하려면 마우스를 이름 위에 올려놓고 (빠른) 을 여십시오.Watch 창을 보거나 Locals 및 Autos와 같은 다양한 디버깅 패널을 사용합니다.

참조 위치를 확인하려면 참조 이름을 마우스 오른쪽 버튼으로 클릭하고 "Find All References(모든 참조 검색)"를 선택합니다.그런 다음 데이터를 요청하는 모든 위치에 중단점을 배치하고 디버거가 연결된 상태에서 프로그램을 실행할 수 있습니다.이러한 중단점에서 디버거가 중단될 때마다 탐색 속성을 채워야 하는지 또는 요청된 데이터가 필요한지 확인해야 합니다.

회피 방법

레이지 로드 비활성화

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

장점: Invalid Operation을 던지는 대신예외는 속성이 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

앞의 예에서 엔티티 프레임워크는 개인과 더불어 반려동물을 구체화한다.이것은 데이터베이스에 대한 단일 호출이기 때문에 편리합니다.(단, 반환된 결과의 수와 요청된 내비게이션속성의 수에 따라 퍼포먼스 문제가 크게 발생할 수 있습니다.이 경우 두 인스턴스는 모두 단일 레코드와 단일 Join에 불과하기 때문에 성능 저하가 발생하지 않습니다).

또는

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는 데이터베이스에서 가져온 개체를 추적하고 일치하는 탐색 속성을 찾으면 이러한 엔티티가 자동으로 채워집니다.이 경우,PetId에서Person오브젝트가 일치합니다.Pet.Id, Entity Framework에 의해Person.Pet에게Pet취득된 값. 이 값은 펫 변수에 할당되기 전에 표시됩니다.

프로그래머가 엔티티 프레임워크를 통해 언제 어떻게 데이터를 요구하는지 이해할 수 있도록 하기 때문에 항상 이 방법을 권장합니다.코드가 엔티티의 속성에 null 참조 예외를 발생시키는 경우 해당 데이터를 명시적으로 요청하지 않았음을 거의 항상 확인할 수 있습니다.

답변이 매우 늦었지만 느린 로드를 해제하는 문제를 해결했습니다.

db.Configuration.LazyLoadingEnabled = false;

ASP를 사용하는 경우.NET Core에서 비동기 컨트롤러 방식 중 하나로 이 메시지가 표시되는 이유를 알고 있습니다.Task보다는void- ASP.NET Core는 주입된 콘텍스트를 폐기합니다.

(이 질문은 검색 결과에서 해당 예외 메시지에 대한 상위 항목이고 미묘한 문제이기 때문에 이 답변을 게시합니다. 구글에서 검색하면 도움이 될 수 있습니다.)

저 같은 경우에는 모든 모델의 '사용자'를 컬럼에 전달하고 있었는데 매핑이 제대로 되지 않아서 그냥 '사용자'를 넘겼어요.'이름' 그리고 고쳐졌지

var data = db.ApplicationTranceLogs 
             .Include(q=>q.Users)
             .Include(q => q.LookupItems) 
             .Select(q => new { Id = q.Id, FormatDate = q.Date.ToString("yyyy/MM/dd"), ***Users = q.Users,*** ProcessType = q.ProcessType, CoreProcessId = q.CoreProcessId, Data = q.Data }) 
             .ToList();

var data = db.ApplicationTranceLogs 
             .Include(q=>q.Users).Include(q => q.LookupItems) 
             .Select(q => new { Id = q.Id, FormatDate = q.Date.ToString("yyyy/MM/dd"), ***Users = q.Users.Name***, ProcessType = q.ProcessType, CoreProcessId = q.CoreProcessId, Data = q.Data }) 
             .ToList();

대부분의 다른 답변은 빠른 로딩에 대한 것입니다만, 저는 다른 해결책을 찾았습니다.

내 경우 EF 오브젝트가 있었는데InventoryItem수집과 함께InvActivity서브 오브젝트

class InventoryItem {
...
   // EF code first declaration of a cross table relationship
   public virtual List<InvActivity> ItemsActivity { get; set; }

   public GetLatestActivity()
   {
       return ItemActivity?.OrderByDescending(x => x.DateEntered).SingleOrDefault();
   }
...
}

컨텍스트 쿼리가 에 (「」를 사용하여)IQueryableInclude()고속 로드를 구현하는 데 사용할 수 없는 함수입니다. 그 이 제 이었습니다.GetLatestActivity() ★★★★★★★★★★★★★★★★★」attach()★★★★★★★★★★★★★★★★★★★★★:

using (DBContext ctx = new DBContext())
{
    var latestAct = _item.GetLatestActivity();

    // attach the Entity object back to a usable database context
    ctx.InventoryActivity.Attach(latestAct);

    // your code that would make use of the latestAct's lazy loading
    // ie   latestAct.lazyLoadedChild.name = "foo";
}

따라서 과도한 부하에 얽매이지 않습니다.

그럴 수도 있겠지요

 -> 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();
            }

언급URL : https://stackoverflow.com/questions/18398356/solving-the-objectcontext-instance-has-been-disposed-and-can-no-longer-be-used

반응형