먼저 쿼리하지 않고 레코드를 업데이트 하시겠습니까?


104

데이터베이스를 쿼리하고 항목 목록을로드한다고 가정 해 보겠습니다. 그런 다음 세부 정보보기 양식에서 항목 중 하나를 열고 데이터베이스에서 항목을 다시 쿼리하는 대신 목록의 데이터 원본에서 항목의 인스턴스를 만듭니다.

개별 항목의 레코드를 가져 오지 않고 데이터베이스 레코드를 업데이트 할 수있는 방법이 있습니까?

다음은 내가 지금 수행하는 방법의 샘플입니다.

dataItem itemToUpdate = (from t in dataEntity.items
                                 where t.id == id
                                 select t).FirstOrDefault();

그런 다음 레코드를 가져온 후 항목의 일부 값을 업데이트하고 레코드를 다시 푸시합니다.

itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();

이 작업을 수행하는 더 좋은 방법이 있다고 생각합니다. 어떤 아이디어라도 있습니까?


2
일을하는 것은별로 나쁜 방법이 아닙니다. 해당 테이블에 대한 동시 액세스 권한이 있습니까?
Henk Holterman

나는 이것이 EF와 같은 ORM이 정확히 봉사하는 사용법이라고 생각합니다. 기본 DB 구현에 대한 걱정없이 생성 / 수정 / 삭제하려는 객체에 대해 애플리케이션 컨텍스트 내에서 작업을 수행 할 수 있도록하려면?
Pero P.

40
ORM을 받아들이고 수용하려는 TSQL에 대한 배경 지식을 가진 개발자에게는 레코드를 업데이트하기 위해서만 조회하고 가져온 데이터를 절대 사용하지 않는 것이 약간 비효율적이라고 생각합니다. 개발자가 기본 DB 구현에 대해 걱정할 필요가 없다는이 개념은 헛소리입니다. 개발자가 전체 시스템에 대해 더 많이 알수록 더 나은 솔루션이 될 수 있습니다. 옵션은 결코 나쁜 것이 아닙니다.
barrypicker

1
ORM 접근 방식은 실제 개체에 적합하지만 데이터베이스에 다른 항목 (예 : 큰 이진 Blob)도 저장하는 경우 원본 콘텐츠를 먼저로드하지 않고 업데이트 할 수있는 것이 매우 유용 할 수 있습니다.
BrainSlugs83

답변:


68

Attach () 메서드를 사용해야합니다 .

개체 연결 및 분리


16
예를 들어 줄 수 있습니까?
Bart Calixto

16
context.Products.Attach (제품); context.Entry (product) .State = EntityState.Modified;
Gabriel

6
@Gabriel 그래도 모든 속성이 업데이트되지 않습니까? 하나만 수정하려면 어떻게해야합니까?
David Pfeffer

22
예, 모든 속성이 업데이트됩니다. 단일 속성을 업데이트하려면 다음과 같이 할 수 있습니다. context.Entry (user) .Property (x => x.Property) .IsModified = true; (여기를 참조하십시오 stackoverflow.com/a/5567616/57369 )
Gabriel

6
해당 컨텍스트를 추가하고 싶습니다 .Entry ()는 .net 4.1에서만 사용할 수 있습니다. 여전히 4.0 (나와 같은)을 사용하는 경우 다음 대안을 확인하십시오. stackoverflow.com/questions/7113434/where-is- 본질적으로 컨텍스트 항목 : context.ObjectStateManager.ChangeObjectState (yourObject, EntityState.Modified);
dyslexicanaboko 2012 년

39

데이터 스토어의 컨텍스트를 사용하여 데이터베이스에 대해 직접 SQL을 사용할 수도 있습니다. 예:

dataEntity.ExecuteStoreCommand
   ("UPDATE items SET itemstatus = 'some status' WHERE id = 123 ");

성능상의 이유로 하드 코딩 된 단일 SQL 문자열 대신 변수를 전달할 수 있습니다. 이렇게하면 SQL Server가 쿼리를 캐시하고 매개 변수와 함께 재사용 할 수 있습니다. 예:

dataEntity.ExecuteStoreCommand
   ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });

업데이트-EF 6.0 용

dataEntity.Database.ExecuteSqlCommand
       ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });

9
댓글을 남기지 않고 왜이 답변을 다운 그레이드할까요? 이 제안은 원래 저자의 질문에 대한 답변입니다.
barrypicker

18
ExecuteStoreCommand이 작업을 수행하는 EF 방식이 아니라 DbConnection내부에 포함 된을 사용하여 DbContext명령을 실행하는 것입니다. 데이터베이스에 구애받지 않고 지속성에 구애받지 않습니다 (예 : OP가 XML로 전환되면이 예제가 중단됨).
just.another.programmer 2013-02-07

9
@ just.another.programmer-큰 힘에는 큰 책임이 따릅니다.
barrypicker 2013

13
지속성에 구애받지 않아야합니까? 격일로 스토리지 시스템을 변경하는 것과는 다릅니다.
David

5
@ BrainSlugs83-OpenQuery 만 지원하는 링크 서버에서 EF를 사용해보세요. 때로는 작업을 완료하기 위해 절대적으로 원시 SQL이 필요합니다. 항상 테스트를 위해 코드를 격리 할 수있는 것은 아닙니다. 완벽한 세상이 아닙니다.
barrypicker

20

코드:

ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 });
exampleEntity.ExampleProperty = "abc";
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();

결과 TSQL :

exec sp_executesql N'UPDATE [dbo].[ExampleEntities]
SET [ExampleProperty ] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1

노트 :

"IsModified = true"줄은 새 ExampleEntity 개체를 만들 때 (ID 속성이 채워진 상태에서만) 다른 모든 속성에 기본값 (0, null 등)이 있기 때문에 필요합니다. "기본값"으로 DB를 업데이트하려는 경우 변경 사항이 엔티티 프레임 워크에서 감지되지 않고 DB가 업데이트되지 않습니다.

예 :

exampleEntity.ExampleProperty = null;

빈 ExampleEntity 개체를 만들 때 ExampleProperty 속성이 이미 null이므로 "IsModified = true"줄이 없으면 작동하지 않습니다.이 열을 업데이트해야한다고 EF에 알려야하며 이것이이 줄의 목적입니다.


이것은 완벽 해요. 나는 이것을 방금 테스트했고 정확히 내가 원했던 것입니다. 변경 사항이 EF 인프라 (EntityFramework.Triggers 프로젝트 사용 포함)를 통과하기를 원하지만 기본 키만있는 상태에서 열 1 개를 변경할 수 있기를 원했습니다.
MikeJansen

11

(가) 경우 DataItem(nullable이 아닌 필드와 같은) EF는 사전 검증하는 필드가 있습니다, 우리는이 상황에 대해 그 유효성을 해제해야합니다 :

DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus };
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.Configuration.ValidateOnSaveEnabled = false;
dataEntity.SaveChanges();
//dataEntity.Configuration.ValidateOnSaveEnabled = true;

그렇지 않으면 사전 검증을 만족하고 단일 열만 업데이트 할 수 있습니다.

DataItem itemToUpdate = new DataItem
{
    Id = id,
    Itemstatus = newStatus,
    NonNullableColumn = "this value is disregarded - the db original will remain"
};
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.SaveChanges();

가정 dataEntitySystem.Data.Entity.DbContext

다음을 추가하여 생성 된 쿼리를 확인할 수 있습니다 DbContext.

/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);


0

EF Core에서 약간 다르게 작동합니다.

EF Core에서이 작업을 수행하는 더 빠른 방법이있을 수 있지만 다음은 SELECT를 수행하지 않고도 UPDATE를 보장합니다 (.NET Framework 4.6.2에서 EF Core 2 및 JET로 테스트 됨).

모델에 IsRequired 속성이 없는지 확인

그런 다음 VB.NET에서 다음 템플릿을 사용합니다.

    Using dbContext = new MyContext()
        Dim bewegung = dbContext.MyTable.Attach(New MyTable())
        bewegung.Entity.myKey = someKey
        bewegung.Entity.myOtherField = "1"

        dbContext.Entry(bewegung.Entity).State = EntityState.Modified
        dbContext.Update(bewegung.Entity)

        Dim BewegungenDescription = (From tp In dbContext.Model.GetEntityTypes() Where tp.ClrType.Name = "MyTable" Select tp).First()
        For Each p In (From prop In BewegungenDescription.GetProperties() Select prop)
            Dim pp = dbContext.Entry(bewegung.Entity).Property(p.Name)
            pp.IsModified = False
        Next
        dbContext.Entry(bewegung.Entity).Property(Function(row) row.myOtherField).IsModified = True
        dbContext.SaveChanges()
    End Using

-1

일반적으로 Entity Framework를 사용하여 모든 항목을 쿼리하고 엔터티 개체를 저장 한 경우 엔터티 개체의 개별 항목을 업데이트하고 SaveChanges()완료되면 호출 할 수 있습니다. 예를 들면 :

var items = dataEntity.Include("items").items;
// For each one you want to change:
items.First(item => item.id == theIdYouWant).itemstatus = newStatus;
// After all changes:
dataEntity.SaveChanges();

원하는 항목을 검색 할 때 새 쿼리가 생성되지 않아야합니다.


흥미로운 대답입니다. 다른 사람이 이것을 확인 했습니까?
Ian

5
이것은 OP의 문제와 같은 일을합니다 : 전체 레코드를 가져온 다음 업데이트합니다. .First ()는 객체를 역 직렬화합니다.
Jerther 2014
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.