[C#] 여러 IEntityChangeTracker 인스턴스에서 엔티티 오브젝트를 참조 할 수 없습니다. Entity Framework 4.1에서 관련 개체를 엔터티에 추가하는 동안

City와 관련된 직원 세부 정보를 저장하려고합니다. 그러나 연락처를 저장하려고 할 때마다 “ADO.Net Entity Framework IEntityChangeTracker의 여러 인스턴스에서 엔터티 개체를 참조 할 수 없습니다” 라는 예외가 발생 합니다.

나는 많은 게시물을 읽었지만 여전히해야 할 일에 대한 정확한 아이디어를 얻지 못했습니다 … 저장 버튼 클릭 코드는 다음과 같습니다.

protected void Button1_Click(object sender, EventArgs e)
    {
        EmployeeService es = new EmployeeService();
        CityService cs = new CityService();

        DateTime dt = new DateTime(2008, 12, 12);
        Payroll.Entities.Employee e1 = new Payroll.Entities.Employee();

        Payroll.Entities.City city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));

        e1.Name = "Archana";
        e1.Title = "aaaa";
        e1.BirthDate = dt;
        e1.Gender = "F";
        e1.HireDate = dt;
        e1.MaritalStatus = "M";
        e1.City = city1;

        es.AddEmpoyee(e1,city1);
    }

직원 서비스 코드

public string AddEmpoyee(Payroll.Entities.Employee e1, Payroll.Entities.City c1)
        {
            Payroll_DAO1 payrollDAO = new Payroll_DAO1();
            payrollDAO.AddToEmployee(e1);  //Here I am getting Error..
            payrollDAO.SaveChanges();
            return "SUCCESS";
        }



답변

이 두 줄 때문에 …

EmployeeService es = new EmployeeService();
CityService cs = new CityService();

… 생성자에 매개 변수를 사용하지 마십시오. 클래스 내에 컨텍스트를 생성한다고 생각합니다. 로드 할 때 city1

Payroll.Entities.City city1 = cs.SelectCity(...);

city1의에 컨텍스트 를 첨부합니다 CityService. 나중에 city1새 참조에 대한 참조로 Employee e1추가 e1 하고이 참조를 포함city1 하여의 컨텍스트에 추가 EmployeeService합니다. 결과적으로 city1예외가 불평하는 두 가지 다른 컨텍스트에 첨부되었습니다.

서비스 클래스 외부에서 컨텍스트를 작성하고 두 서비스 모두에서 컨텍스트를 삽입하고 사용하여이 문제를 해결할 수 있습니다.

EmployeeService es = new EmployeeService(context);
CityService cs = new CityService(context); // same context instance

서비스 클래스는 단일 엔터티 유형 만 담당하는 리포지토리와 비슷합니다. 이 경우 서비스에 별도의 컨텍스트를 사용할 때 엔티티 간의 관계가 시작 되 자마자 항상 문제가 발생합니다.

또한 EmployeeCityService(단일 컨텍스트가있는) 밀접하게 관련된 엔티티 세트를 담당하는 단일 서비스를 작성하고 Button1_Click메소드 의 전체 조작 을이 서비스의 메소드에 위임 할 수도 있습니다.


답변

재현 단계는 다음과 같이 단순화 할 수 있습니다.

var contextOne = new EntityContext();
var contextTwo = new EntityContext();

var user = contextOne.Users.FirstOrDefault();

var group = new Group();
group.User = user;

contextTwo.Groups.Add(group);
contextTwo.SaveChanges();

오류없는 코드 :

var context = new EntityContext();

var user = context.Users.FirstOrDefault();

var group = new Group();
group.User = user; // Be careful when you set entity properties. 
// Be sure that all objects came from the same context

context.Groups.Add(group);
context.SaveChanges();

하나만 사용하면 EntityContext이 문제를 해결할 수 있습니다. 다른 솔루션에 대해서는 다른 답변을 참조하십시오.


답변

이것은 오래된 스레드이지만 선호하는 또 다른 솔루션은 cityId를 업데이트하고 구멍 모델 City를 Employee에 할당하지 않는 것입니다.

public class Employee{
    ...
    public int? CityId; //The ? is for allow City nullable
    public virtual City City;
}

그런 다음 충분하게 할당하십시오.

e1.CityId=city1.ID;


답변

주입 및 더 나쁜 Singleton 대신 Add 전에 Detach 메서드를 호출 할 수 있습니다 .

엔티티 프레임 워크 6 : ((IObjectContextAdapter)cs).ObjectContext.Detach(city1);

EntityFramework 4 : cs.Detach(city1);

첫 번째 DBContext 객체가 필요하지 않은 경우 다른 방법이 있습니다. 키워드 를 사용하여 감싸십시오 .

Payroll.Entities.City city1;
using (CityService cs = new CityService())
{
  city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
}


답변

나는 같은 문제가 있었지만 @Slauma의 솔루션에 대한 내 문제 (특정 인스턴스에서는 크지 만)는 컨텍스트를 서비스에 전달하여 컨트롤러에서 컨텍스트를 사용할 수 있음을 암시하는 것이 좋습니다. 또한 컨트롤러와 서비스 계층간에 긴밀한 연결을 강제합니다.

서비스 / 리포지토리 레이어를 컨트롤러에 주입하기 위해 Dependency Injection을 사용하고 있으므로 컨트롤러의 컨텍스트에 액세스 할 수 없습니다.

내 솔루션은 서비스 / 리포지토리 레이어가 동일한 컨텍스트 인스턴스 인 Singleton을 사용하도록하는 것입니다.

컨텍스트 싱글턴 클래스 :

참조 : http://msdn.microsoft.com/en-us/library/ff650316.aspx
http://csharpindepth.com/Articles/General/Singleton.aspx

public sealed class MyModelDbContextSingleton
{
  private static readonly MyModelDbContext instance = new MyModelDbContext();

  static MyModelDbContextSingleton() { }

  private MyModelDbContextSingleton() { }

  public static MyModelDbContext Instance
  {
    get
    {
      return instance;
    }
  }
}  

리포지토리 클래스 :

public class ProjectRepository : IProjectRepository
{
  MyModelDbContext context = MyModelDbContextSingleton.Instance;
  [...]

컨텍스트를 한 번 인스턴스화하여 서비스 / 저장소 계층의 생성자 또는 작업 단위 패턴을 구현하는 다른 솔루션으로 전달하는 것과 같은 다른 솔루션이 있습니다. 더 많은 것이 있다고 확신합니다 …


답변

필자의 경우 ASP.NET Identity Framework를 사용하고있었습니다. 엔티티 UserManager.FindByNameAsync를 검색하기 위해 내장 메소드를 사용했습니다 ApplicationUser. 그런 다음 다른 엔터티에서 새로 만든 엔터티에서이 엔터티를 참조하려고했습니다 DbContext. 이로 인해 원래 본 예외가 발생했습니다.

메소드 ApplicationUser에서만 Idfrom을 사용하여 새 엔티티를 작성하고 UserManager해당 새 엔티티를 참조 하여이를 해결했습니다 .


답변

나는 같은 문제가 있었고 업데이트하려고하는 객체의 새 인스턴스를 만들 수 있습니다. 그런 다음 그 대상을 내 철학자에게 전달했습니다.