Entity Framework를 사용하여 테이블에서 여러 항목을 삭제하고 있습니다. 외래 키 / 부모 개체가 없으므로 OnDeleteCascade 로이를 처리 할 수 없습니다.
지금 나는 이것을하고있다 :
var widgets = context.Widgets
.Where(w => w.WidgetId == widgetId);
foreach (Widget widget in widgets)
{
context.Widgets.DeleteObject(widget);
}
context.SaveChanges();
그것은 효과가 있지만 foreach는 나를 버그로 만듭니다. EF4를 사용하고 있지만 SQL을 실행하고 싶지 않습니다. 나는 단지 내가 빠진 것이 없는지 확인하고 싶습니다-이것이 얻는 것만 큼 좋습니다. 확장 방법이나 도우미로 추상화 할 수 있지만 어딘가에서 foreach를 수행 할 것입니다.
답변
루프에서 DeleteObject를 직접 호출하여 SQL을 실행하지 않으려면 오늘 최선을 다하십시오.
그러나 여기에 설명 된 접근 방식을 사용하여 SQL을 실행하고 확장 방법을 통해 완전히 범용으로 만들 수 있습니다 .
그 대답은 3.5였습니다. 4.0의 경우 아마도 StoreConnection으로 드롭 다운하는 대신 새로운 ExecuteStoreCommand API를 사용합니다.
답변
EntityFramework 6을 사용하면이 작업을보다 쉽게 수행 할 수 있습니다 .RemoveRange()
.
예:
db.People.RemoveRange(db.People.Where(x => x.State == "CA"));
db.SaveChanges();
답변
이것이 얻는 것만 큼 좋습니다. 확장 방법이나 도우미로 추상화 할 수 있지만 어딘가에서 foreach를 수행 할 것입니다.
네, 두 개의 라이너로 만들 수 있다는 점을 제외하고는 :
context.Widgets.Where(w => w.WidgetId == widgetId)
.ToList().ForEach(context.Widgets.DeleteObject);
context.SaveChanges();
답변
using (var context = new DatabaseEntities())
{
context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
}
답변
나는 그것이 늦었다는 것을 알고 있지만 누군가가 간단한 해결책이 필요한 경우 멋진 점은 where 절을 추가 할 수 있다는 것입니다.
public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
string selectSql = db.Set<T>().Where(filter).ToString();
string fromWhere = selectSql.Substring(selectSql.IndexOf("FROM"));
string deleteSql = "DELETE [Extent1] " + fromWhere;
db.Database.ExecuteSqlCommand(deleteSql);
}
참고 : MSSQL2008로 방금 테스트했습니다.
최신 정보:
EF가 parameters로 sql 문을 생성 할 때 위의 솔루션이 작동하지 않으므로 EF5에 대한 업데이트가 있습니다 .
public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
var query = db.Set<T>().Where(filter);
string selectSql = query.ToString();
string deleteSql = "DELETE [Extent1] " + selectSql.Substring(selectSql.IndexOf("FROM"));
var internalQuery = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_internalQuery").Select(field => field.GetValue(query)).First();
var objectQuery = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_objectQuery").Select(field => field.GetValue(internalQuery)).First() as ObjectQuery;
var parameters = objectQuery.Parameters.Select(p => new SqlParameter(p.Name, p.Value)).ToArray();
db.Database.ExecuteSqlCommand(deleteSql, parameters);
}
약간의 반사가 필요하지만 잘 작동합니다.
답변
EF5를 사용하는 사람은 다음 확장 라이브러리를 사용할 수 있습니다. https://github.com/loresoft/EntityFramework.Extended
context.Widgets.Delete(w => w.WidgetId == widgetId);
답변
서버를 삭제하기 위해 서버에서 무언가를 가져와야하는 것은 여전히 미치게 보이지만 적어도 ID 만 다시 가져 오는 것이 전체 엔티티를 끌어내는 것보다 훨씬 느립니다.
var ids = from w in context.Widgets where w.WidgetId == widgetId select w.Id;
context.Widgets.RemoveRange(from id in ids.AsEnumerable() select new Widget { Id = id });
