엔티티 프레임 워크, 관련 개체 업데이트 문제
현재 Entity Framework의 최신 버전을 사용하는 프로젝트를 진행 중이며 해결할 수없는 문제를 발견했습니다.
기존 객체를 업데이트 할 때 다른 클래스에 대한 참조 인 속성이 나올 때까지 객체 속성을 상당히 쉽게 업데이트 할 수 있습니다.
아래 예제에는 다양한 속성을 저장하는 Foo라는 클래스가 있으며이 중 2 개는 다른 클래스의 인스턴스입니다.
public class Foo
{
public int Id {get; set;}
public string Name {get; set;}
public SubFoo SubFoo {get; set}
public AnotherSubFoo AnotherSubFoo {get; set}
}
아래 Edit()
방법을 사용할 때 업데이트하려는 객체를 전달 Name
하고 제대로 업데이트 할 수 있도록 관리 할 수 있지만 SubFoo의 속성을 변경하는 방법을 찾지 못했습니다. 예를 들어 SubFoo
클래스의 속성이이고이 속성 Name
이 변경되어 내 DB와에서 다른 newFoo
경우 업데이트되지 않습니다.
public Foo Edit(Foo newFoo)
{
var dbFoo = context.Foo
.Include(x => x.SubFoo)
.Include(x => x.AnotherSubFoo)
.Single(c => c.Id == newFoo.Id);
var entry = context.Entry<Foo>(dbFoo);
entry.OriginalValues.SetValues(dbFoo);
entry.CurrentValues.SetValues(newFoo);
context.SaveChanges();
return newFoo;
}
어떤 도움이나 조언을 주시면 대단히 감사하겠습니다.
업데이트 : Slauma의 의견에 따라 방법을 다음과 같이 수정했습니다.
public Foo Edit(Foo newFoo)
{
var dbFoo = context.Foo
.Include(x => x.SubFoo)
.Include(x => x.AnotherSubFoo)
.Single(c => c.Id == newFoo.Id);
context.Entry(dbFoo).CurrentValues.SetValues(newFoo);
context.Entry(dbFoo.SubFoo).CurrentValues.SetValues(newFoo.SubFoo);
context.SaveChanges();
return newFoo;
}
지금 실행할 때 오류가 발생합니다.
엔티티 유형 Collection`1은 현재 컨텍스트에 대한 모델의 일부가 아닙니다.
이 문제를 해결하기 위해 newFoo
하위 클래스를 컨텍스트 에 연결하는 코드를 추가 했지만 ObjectManager
이미 동일한 엔터티가 있다는 오류가 발생했습니다 .
동일한 키를 가진 개체가 ObjectStateManager에 이미 있습니다. ObjectStateManager는 동일한 키로 여러 개체를 추적 할 수 없습니다.
CurrentValues.SetValues
스칼라 속성 만 업데이트하고 관련 항목은 업데이트하지 않으므로 각 관련 항목에 대해 동일한 작업을 수행해야합니다.
public Foo Edit(Foo newFoo)
{
var dbFoo = context.Foo
.Include(x => x.SubFoo)
.Include(x => x.AnotherSubFoo)
.Single(c => c.Id == newFoo.Id);
context.Entry(dbFoo).CurrentValues.SetValues(newFoo);
context.Entry(dbFoo.SubFoo).CurrentValues.SetValues(newFoo.SubFoo);
context.Entry(dbFoo.AnotherSubFoo).CurrentValues.SetValues(newFoo.AnotherSubFoo);
context.SaveChanges();
return newFoo;
}
관계가 완전히 제거되었거나 생성 된 경우 해당 사례도 명시 적으로 처리해야합니다.
public Foo Edit(Foo newFoo)
{
var dbFoo = context.Foo
.Include(x => x.SubFoo)
.Include(x => x.AnotherSubFoo)
.Single(c => c.Id == newFoo.Id);
context.Entry(dbFoo).CurrentValues.SetValues(newFoo);
if (dbFoo.SubFoo != null)
{
if (newFoo.SubFoo != null)
{
if (dbFoo.SubFoo.Id == newFoo.SubFoo.Id)
// no relationship change, only scalar prop.
context.Entry(dbFoo.SubFoo).CurrentValues.SetValues(newFoo.SubFoo);
else
{
// Relationship change
// Attach assumes that newFoo.SubFoo is an existing entity
context.SubFoos.Attach(newFoo.SubFoo);
dbFoo.SubFoo = newFoo.SubFoo;
}
}
else // relationship has been removed
dbFoo.SubFoo = null;
}
else
{
if (newFoo.SubFoo != null) // relationship has been added
{
// Attach assumes that newFoo.SubFoo is an existing entity
context.SubFoos.Attach(newFoo.SubFoo);
dbFoo.SubFoo = newFoo.SubFoo;
}
// else -> old and new SubFoo is null -> nothing to do
}
// the same logic for AnotherSubFoo ...
context.SaveChanges();
return newFoo;
}
결국 Modified
관계가 변경된 경우 연결된 엔터티의 상태 와 스칼라 속성도 설정해야합니다.
편집하다
귀하의 의견에 따르면 Foo.SubFoo
실제로 컬렉션이고 참조 일뿐 아니라 관련 엔터티를 업데이트하려면 다음과 같은 것이 필요합니다.
public Foo Edit(Foo newFoo)
{
var dbFoo = context.Foo
.Include(x => x.SubFoo)
.Include(x => x.AnotherSubFoo)
.Single(c => c.Id == newFoo.Id);
// Update foo (works only for scalar properties)
context.Entry(dbFoo).CurrentValues.SetValues(newFoo);
// Delete subFoos from database that are not in the newFoo.SubFoo collection
foreach (var dbSubFoo in dbFoo.SubFoo.ToList())
if (!newFoo.SubFoo.Any(s => s.Id == dbSubFoo.Id))
context.SubFoos.Remove(dbSubFoo);
foreach (var newSubFoo in newFoo.SubFoo)
{
var dbSubFoo = dbFoo.SubFoo.SingleOrDefault(s => s.Id == newSubFoo.Id);
if (dbSubFoo != null)
// Update subFoos that are in the newFoo.SubFoo collection
context.Entry(dbSubFoo).CurrentValues.SetValues(newSubFoo);
else
// Insert subFoos into the database that are not
// in the dbFoo.subFoo collection
dbFoo.SubFoo.Add(newSubFoo);
}
// and the same for AnotherSubFoo...
db.SaveChanges();
return newFoo;
}
관련 엔터티를 업데이트하는 방법을 이해하는 데 도움이 되었기 때문에 아래 링크를 게시 할 것이라고 생각했습니다.
Updating related data with the entity framework in an asp net mvc application
NOTE: I did change the logic slightly that is shown in the UpdateInstructorCourses function to suit my needs.
You can also call the tables independently
MyContext db = new MyContext
// I like using asynchronous calls in my API methods
var OldFoo = await db.Foo.FindAsync(id);
var OldAssociateFoo = db.AssociatedFoo;
var NewFoo = OldFoo;
var NewAssociatedFoo = OldAssociatedFoo;
NewFoo.SomeValue = "The Value";
NewAssociatedFoo.OtherValue = 20;
db.Entry(OldFoo).CurrentValues.SetValues(NewFoo);
db.Entry(OldAssociatedFoo).CurrentValues.SetValues(NewAssociatedFoo);
await db.SaveChangesAsync();
ReferenceURL : https://stackoverflow.com/questions/13236116/entity-framework-problems-updating-related-objects
'Programing' 카테고리의 다른 글
FORM 태그 의미 체계 html5 외부의 양식 요소가 있습니까? (0) | 2020.12.25 |
---|---|
HttpServletResponse sendRedirect 영구 (0) | 2020.12.25 |
Android Studio 빌드에서 클래스 제외? (0) | 2020.12.25 |
Xcode의 자산 카탈로그에 JPEG를 어떻게 추가 할 수 있습니까? (0) | 2020.12.25 |
Redux에서 상태를 업데이트 한 후 콜백을 트리거하는 방법은 무엇입니까? (0) | 2020.12.25 |