엔티티 프레임 작업 코어에서 데이터베이스 테이블 데이터를 업데이트하는 가장 좋은 방법은 무엇입니까?
- 테이블 행을 검색하고 변경을 수행하고 저장하십시오.
- DB 컨텍스트에서 키워드 업데이트 를 사용 하고 존재하지 않는 항목에 대한 예외 처리
EF6에서 사용할 수있는 향상된 기능은 무엇입니까?
답변:
Entity Framework Core로 엔터티를 업데이트하기위한 논리적 프로세스는 다음과 같습니다.
DbContext
클래스에 대한 인스턴스 만들기Update()
방법 DbContext
:
SaveChanges()
호출 될 때 데이터베이스에서 업데이트되도록 수정 됨 상태에서 지정된 엔티티 추적을 시작합니다 .
업데이트 방법은 데이터베이스에 변경 사항을 저장하지 않습니다. 대신 DbContext 인스턴스의 항목에 대한 상태를 설정합니다.
따라서 Update()
데이터베이스에 변경 사항을 저장하기 전에 메서드를 호출 할 수 있습니다 .
귀하의 질문에 답하기 위해 몇 가지 객체 정의를 가정하겠습니다.
데이터베이스 이름은 Store입니다.
테이블 이름은 제품입니다.
제품 클래스 정의 :
public class Product
{
public int? ProductID { get; set; }
public string ProductName { get; set; }
public string Description { get; set; }
public decimal? UnitPrice { get; set; }
}
DbContext 클래스 정의 :
public class StoreDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Your Connection String");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>(entity =>
{
// Set key for entity
entity.HasKey(p => p.ProductID);
});
base.OnModelCreating(modelBuilder);
}
}
엔티티 업데이트 로직 :
using (var context = new StoreDbContext())
{
// Retrieve entity by id
// Answer for question #1
var entity = context.Products.FirstOrDefault(item => item.ProductID == id);
// Validate entity is not null
if (entity != null)
{
// Answer for question #2
// Make changes on entity
entity.UnitPrice = 49.99m;
entity.Description = "Collector's edition";
/* If the entry is being tracked, then invoking update API is not needed.
The API only needs to be invoked if the entry was not tracked.
https://www.learnentityframeworkcore.com/dbcontext/modifying-data */
// context.Products.Update(entity);
// Save changes in database
context.SaveChanges();
}
}
int?
을 사용 ProductID
했나요? 선택적 기본 키가됩니까?
Microsoft 문서 에 따르면 :
읽기 우선 접근 방식에는 추가 데이터베이스 읽기가 필요하며 동시성 충돌을 처리하기 위해 더 복잡한 코드가 발생할 수 있습니다.
그러나 DbContext에서 Update 메서드를 사용하면 모든 필드가 수정 된 것으로 표시되고 모든 필드 가 쿼리에 포함 된다는 것을 알아야 합니다. 필드의 하위 집합을 업데이트하려면 Attach 메서드를 사용한 다음 원하는 필드를 수동 으로 수정 된 것으로 표시 해야합니다.
context.Attach(person);
context.Entry(person).Property(p => p.Name).IsModified = true;
context.SaveChanges();
context.Entry(person).Property(p => p.Name).IsModified = true;
context.Entry(person).State = EntityState.Modified;
_context.Attach(person).State = EntityState.Modified;
경우이 엔터티가 SaveChanges 메서드에서 업데이트 될 것임을 나타내는 데 사용할 수 있습니다 .
public async Task<bool> Update(MyObject item)
{
Context.Entry(await Context.MyDbSet.FirstOrDefaultAsync(x => x.Id == item.Id)).CurrentValues.SetValues(item);
return (await Context.SaveChangesAsync()) > 0;
}
Microsoft Docs 는 두 가지 접근 방식을 제공합니다.
권장 HttpPost 편집 코드 : 읽기 및 업데이트
이것은 이전 버전의 Entity Framework에서 사용했던 것과 동일한 이전 방식입니다. 이것이 Microsoft가 우리에게 권장하는 것입니다.
장점
Modified
양식 입력에 의해 변경되는 필드에 플래그를 설정합니다 .대체 HttpPost 편집 코드 : 생성 및 첨부
대안은 모델 바인더로 만든 엔터티를 EF 컨텍스트에 연결하고 수정 된 것으로 표시하는 것입니다.
다른 답변에서 언급했듯이 읽기 우선 접근 방식에는 추가 데이터베이스 읽기가 필요하며 동시성 충돌을 처리하기 위해 더 복잡한 코드가 발생할 수 있습니다.
아주 간단합니다
using (var dbContext = new DbContextBuilder().BuildDbContext())
{
dbContext.Update(entity);
await dbContext.SaveChangesAsync();
}
모든 답을 살펴본 후 두 가지 간단한 옵션을 추가 할 것이라고 생각했습니다.
추적이 활성화 된 상태에서 FirstOrDefault ()를 사용하여 레코드에 이미 액세스하고 (추적을 비활성화하므로 .AsNoTracking () 함수를 사용하지 않고) 일부 필드를 업데이트 한 경우 간단히 context.SaveChanges ()를 호출 할 수 있습니다.
다른 경우에는 HtppPost를 사용하여 서버에 엔티티를 게시했거나 어떤 이유로 추적을 비활성화 한 다음 context.SaveChanges () 전에 context.Update (entityName)를 호출해야합니다.
첫 번째 옵션은 변경 한 필드 만 업데이트하지만 두 번째 옵션은 실제로 업데이트 된 필드 값이 없더라도 데이터베이스의 모든 필드를 업데이트합니다. :)
보다 일반적인 접근 방식
이 접근 방식을 단순화하기 위해 "id"인터페이스가 사용됩니다.
public interface IGuidKey
{
Guid Id { get; set; }
}
도우미 방법
public static void Modify<T>(this DbSet<T> set, Guid id, Action<T> func)
where T : class, IGuidKey, new()
{
var target = new T
{
Id = id
};
var entry = set.Attach(target);
func(target);
foreach (var property in entry.Properties)
{
var original = property.OriginalValue;
var current = property.CurrentValue;
if (ReferenceEquals(original, current))
{
continue;
}
if (original == null)
{
property.IsModified = true;
continue;
}
var propertyIsModified = !original.Equals(current);
property.IsModified = propertyIsModified;
}
}
용법
dbContext.Operations.Modify(id, x => { x.Title = "aaa"; });