엔티티 개체는 IEentityChangeTracker의 여러 인스턴스에서 참조할 수 없습니다.Entity Framework 4.1에서 엔티티에 관련 개체를 추가하는 동안
시티와 관련된 직원 세부사항을 저장하려고 합니다.그러나 확인된 연락처를 저장하려고 할 때마다 "ADO" 예외가 발생합니다.NetEntityFramework 엔티티 개체를 IEentityChangeTracker의 여러 인스턴스에서 참조할 수 없습니다."
너무 많은 게시물을 읽었지만 여전히 어떻게 해야 할지 정확히 모르겠습니다... 제 저장 버튼 클릭 코드는 아래에 나와 있습니다.
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
의 맥락에 대한 이 참조를 포함하여.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 모델을 직원에게 할당하지 않는 것입니다.이를 위해 직원은 다음과 같이 보여야 합니다.
public class Employee{
...
public int? CityId; //The ? is for allow City nullable
public virtual City City;
}
그러면 다음을 할당하는 것으로 충분합니다.
e1.CityId=city1.ID;
주입이나 더 나쁜 싱글턴 대신 추가하기 전에 분리 방법을 호출할 수 있습니다.
6: 엔프티워크 6:((IObjectContextAdapter)cs).ObjectContext.Detach(city1);
4: 크엔티프워임 4:cs.Detach(city1);
첫 번째 DB 컨텍스트 개체가 필요하지 않을 경우를 대비하여 다른 방법이 있습니다.키워드를 사용하여 마무리하면 됩니다.
Payroll.Entities.City city1;
using (CityService cs = new CityService())
{
city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
}
저도 같은 문제가 있었지만 @Slauma의 솔루션(일부 경우에는 훌륭하지만)의 문제는 컨트롤러에서 컨텍스트를 사용할 수 있다는 것을 암시하는 서비스에 컨텍스트를 전달하는 것을 권장한다는 것입니다.또한 컨트롤러와 서비스 계층 간의 긴밀한 결합이 필요합니다.
종속성 주입을 사용하여 서비스/리포지토리 계층을 컨트롤러에 주입하고 있으므로 컨트롤러에서 컨텍스트에 액세스할 수 없습니다.
제 솔루션은 서비스/저장소 계층에서 컨텍스트의 동일한 인스턴스(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
다만포엔티티만 Id
UserManager
메서드 및 새 엔티티를 참조합니다.
저는 프로젝트(ASP)를 위해 IoC를 구현한 후에 이와 같은 문제에 부딪혔습니다.순 MVC EF6.2).
보통 컨트롤러의 생성자에서 데이터 컨텍스트를 초기화하고 동일한 컨텍스트를 사용하여 모든 리포지토리를 초기화합니다.
하지만 IoC를 사용하여 저장소를 인스턴스화하는 것은 모든 저장소에 별도의 컨텍스트가 생기게 했고 저는 이 오류를 받기 시작했습니다.
이제는 더 나은 방법을 생각하는 동안 공통된 맥락에서 저장소를 새로 만드는 것으로 돌아갔습니다.
이것이 제가 이 문제에 직면한 방법입니다.우선 나는 나의 것을 저장해야 합니다.Order
나의 것에 대한 참조가 필요합니다.ApplicationUser
테이블:
ApplicationUser user = new ApplicationUser();
user = UserManager.FindById(User.Identity.GetUserId());
Order entOrder = new Order();
entOrder.ApplicationUser = user; //I need this user before saving to my database using EF
가 새로운 ApplicationDbContext를 입니다.Order
엔티티:
ApplicationDbContext db = new ApplicationDbContext();
db.Entry(entOrder).State = EntityState.Added;
db.SaveChanges();
그래서 문제를 해결하기 위해 ASP.NET MVC의 내장 UserManager를 사용하는 대신 동일한 ApplicationDbContext를 사용했습니다.
이 대신:
user = UserManager.FindById(User.Identity.GetUserId());
기존 ApplicationDbContext 인스턴스를 사용했습니다.
//db instance here is the same instance as my db on my code above.
user = db.Users.Find(User.Identity.GetUserId());
저도 같은 문제가 있었고 업데이트하려는 개체의 새 인스턴스를 만드는 문제를 해결할 수 있었습니다.그리고 나서 저는 그 물체를 제 저장소로 넘겼습니다.
이 경우 오류가 매우 명확한 것으로 나타났습니다.엔티티 프레임워크는 다음의 여러 인스턴스를 사용하여 엔티티를 추적할 수 없습니다.IEntityChangeTracker
또는 일반적으로 의 여러 인스턴스DbContext
솔루션은 다음과 같습니다.DbContext
단일 저장소를 통해 필요한 모든 엔티티에 액세스합니다(하나의 인스턴스에 따라 다름).DbContext
또는 이 특정 예외를 발생시키는 항목이 아닌 리포지토리를 통해 액세스하는 모든 엔티티에 대한 추적을 해제합니다.
에서 제어 패턴의 반전을 따를 때.NetCore Web API에서는 다음과 같은 종속성을 가진 컨트롤러를 자주 발견합니다.
private readonly IMyEntityRepository myEntityRepo; // depends on MyDbContext
private readonly IFooRepository fooRepo; // depends on MyDbContext
private readonly IBarRepository barRepo; // depends on MyDbContext
public MyController(
IMyEntityRepository myEntityRepo,
IFooRepository fooRepo,
IBarRepository barRepo)
{
this.fooRepo = fooRepo;
this.barRepo = barRepo;
this.myEntityRepo = myEntityRepo;
}
그리고 같은 용법.
...
myEntity.Foo = await this.fooRepository.GetFoos().SingleOrDefaultAsync(f => f.Id == model.FooId);
if (model.BarId.HasValue)
{
myEntity.Foo.Bar = await this.barRepository.GetBars().SingleOrDefaultAsync(b => b.Id == model.BarId.Value);
}
...
await this.myEntityRepo.UpdateAsync(myEntity); // this throws an error!
세 개의 리포지토리가 모두 서로 다른 환경에 종속되어 있기 때문입니다.DbContext
요청당 인스턴스 수는 문제를 방지하고 별도의 저장소를 유지하는 두 가지 옵션이 있습니다. 호출당 한 번만 새 인스턴스를 생성하도록 DbContext 주입을 변경하는 것입니다.
// services.AddTransient<DbContext, MyDbContext>(); <- one instance per ctor. bad
services.AddScoped<DbContext, MyDbContext>(); // <- one instance per call. good!
또는 자식 엔티티가 읽기 전용 방식으로 사용되는 경우 해당 인스턴스에 대한 추적을 해제합니다.
myEntity.Foo.Bar = await this.barRepo.GetBars().AsNoTracking().SingleOrDefault(b => b.Id == model.BarId);
트랜잭션 전체에서 동일한 DB 컨텍스트 개체를 사용합니다.
이 시나리오에서는 동일한 컨텍스트를 참조하는 여러 애플리케이션을 사용하는 솔루션이 있습니다.컨텍스트에 수명 유형을 추가하여 unity.config 파일을 업데이트해야 했습니다.
<lifetime type="PerResolveLifetimeManager" />
오류 소스:
ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.Name);
ApplicationDbContext db = new ApplicationDbContent();
db.Users.Uploads.Add(new MyUpload{FileName="newfile.png"});
await db.SavechangesAsync();/ZZZZZZZ
누군가가 소중한 시간을 절약하기를 바랍니다.
언급URL : https://stackoverflow.com/questions/10191734/entity-object-cannot-be-referenced-by-multiple-instances-of-ientitychangetracker
'programing' 카테고리의 다른 글
ng2 - ng-container 태그와 ng-template 태그의 차이 (0) | 2023.06.02 |
---|---|
데이터 클래스의 클래스 특성 선언에서 기본값을 변경할 수 없는 이유는 무엇입니까? (0) | 2023.05.28 |
mongodb 쉘은 어떻게 시작하나요? (0) | 2023.05.28 |
레이블과 텍스트 블록의 차이 (0) | 2023.05.28 |
MongoDB 인스턴스에 대한 클라이언트가 유효한지 어떻게 확인합니까? (0) | 2023.05.28 |