엔티티 프레임워크의 모든 엔티티 삭제
Entity Framework 4+를 사용하여 모든 테이블(모든 엔터티)의 내용을 삭제하려고 합니다.이것이 어떻게 행해지는가?
이렇게 하면 기본 데이터베이스가 MSSQL이라고 가정할 때 개별 엔터티 개체를 삭제하는 것보다 훨씬 더 효과적으로 수행됩니다.
foreach (var tableName in listOfTableNames)
{
context.ExecuteStoreCommand("TRUNCATE TABLE [" + tableName + "]");
}
물론 테이블에 외래 키 관계가 있는 경우 외래 키 테이블을 삭제하기 전에 외래 키 테이블을 삭제할 수 있도록 테이블 이름 목록을 적절한 순서로 설정해야 합니다.
게으른 사람들을 위해, 답을 찾을 때 내가 직접 떠올린 코드:
public static void ClearDatabase<T>() where T : DbContext, new()
{
using (var context = new T())
{
var tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%'").ToList();
foreach (var tableName in tableNames)
{
context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableName));
}
context.SaveChanges();
}
}
간단한 설명:권한 부족으로 인해 테이블을 자르지는 않습니다. 문제가 되지 않는다면 언제든지 잘라내십시오.__Migration 테이블where 문에서 기록을 무시합니다.
업데이트: 몇 가지 조사를 통해 더 나은 솔루션을 찾았습니다(별로 좋지는 않지만 필요한 열만 삭제).
public static void ClearDatabase(DbContext context)
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var entities = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace).BaseEntitySets;
var method = objectContext.GetType().GetMethods().First(x => x.Name == "CreateObjectSet");
var objectSets = entities.Select(x => method.MakeGenericMethod(Type.GetType(x.ElementType.FullName))).Select(x => x.Invoke(objectContext, null));
var tableNames = objectSets.Select(objectSet => (objectSet.GetType().GetProperty("EntitySet").GetValue(objectSet, null) as EntitySet).Name).ToList();
foreach (var tableName in tableNames)
{
context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableName));
}
context.SaveChanges();
}
EF 6의 경우:
DbSet<Entity>.RemoveRange(DbSet<Entity>);
다음과 같은 코드를 사용하여 표를 반복합니다.
context.GetType().GetProperties()
.Where(propertyInfo => propertyInfo.PropertyType == typeof(Table<>))
.Select(propertyInfo => propertyInfo.GetValue(context, null) as ITable).ToList()
.Foreach(table =>
{
//code that deletes the actual tables records.
}
);
저는 @Wojciech Markowski의 훌륭한 답변을 개선하기 위해 노력하고 싶습니다.
나처럼 게으르고 외래 키 제약 조건을 확인하고 싶지 않다면 다음 방법을 사용할 수 있습니다.
private void ClearDatabase(TContext context)
{
// disable all foreign keys
//context.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable @command1 = 'ALTER TABLE ? NOCHECK CONSTRAINT all'");
List<string> tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%'").ToList();
for (int i = 0; tableNames.Count>0; i++)
{
try
{
context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableNames.ElementAt(i % tableNames.Count)));
tableNames.RemoveAt(i % tableNames.Count);
i = 0;
}
catch { } // ignore errors as these are expected due to linked foreign key data
}
context.SaveChanges();
}
ClearDatabase 메서드는 테이블 목록을 검토한 후 정리합니다. FK 제약 조건이 발견되면 예외를 적용하고 다음 테이블로 이동합니다.마지막에 모든 테이블이 삭제됩니다.
또한 모든 FK 제약 조건을 해제하는 것이 괜찮다면 라인을 사용하여 모든 제약 조건을 비활성화할 수 있습니다.
context.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable @command1 = 'ALTER TABLE ? NOCHECK CONSTRAINT all'");
한 가지 더:삭제하지 않고 모든 테이블을 삭제하려면 다음 행을 바꿉니다.
context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableNames.ElementAt(i % tableNames.Count)));
포함:
context.Database.ExecuteSqlCommand(string.Format("DROP TABLE {0}", tableNames.ElementAt(i % tableNames.Count)));
코드 우선 마이그레이션으로 엔티티 프레임워크 6에서 이 답변을 직접 확인했습니다.
편집: 더 나은 버전:
private void ClearDatabase(MrSaleDbContext context)
{
//Optional: disable all foreign keys (db-schema will be loosed).
//context.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable @command1 = 'ALTER TABLE ? NOCHECK CONSTRAINT all'");
List<string> tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%' AND TABLE_NAME NOT LIKE 'AspNet%'").ToList();
for (int i = 0; tableNames.Count > 0; i++)
{
try
{
//To delete all tables and not just clean them from data, replace "DELETE FROM {0}" in "DROP TABLE {0}":
context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableNames.ElementAt(i % tableNames.Count)));
tableNames.RemoveAt(i % tableNames.Count);
i = -1; //flag: a table was removed. in the next iteration i++ will be the 0 index.
}
catch (System.Data.SqlClient.SqlException e) // ignore errors as these are expected due to linked foreign key data
{
if ((i % tableNames.Count) == (tableNames.Count - 1))
{
//end of tables-list without any success to delete any table, then exit with exception:
throw new System.Data.DataException("Unable to clear all relevant tables in database (foriegn key constraint ?). See inner-exception for more details.", e);
}
}
}
catch 블록의 if 문은 테이블을 삭제하지 않고 테이블 목록의 마지막 인덱스에 도달했는지 확인합니다.이 경우 무한 루프 대신 예외를 던지고 를 종료합니다.
(In.NetCore) 테이블에서 RemoveRange를 사용하고 테이블 자체를 Parameter(파라미터)로 지정할 수 있습니다.
Tablename.RemoveRange(Tablename);
외부 키 내에서 잘라낼 수 없습니다.
그런 다음 DbContext에 대한 확장 방법을 만들었습니다.
사용법은 간단합니다.
db.cruncates(); // 모든 테이블을 삭제합니다.
db.cruncates("Test1", "Test2"); // "Test1, Test2" 테이블만 삭제
public static class DbContextExtension
{
public static int Truncates(this DbContext db, params string[] tables)
{
List<string> target = new List<string>();
int result = 0;
if (tables == null || tables.Length == 0)
{
target = db.GetTableList();
}
else
{
target.AddRange(tables);
}
using (TransactionScope scope = new TransactionScope())
{
foreach (var table in target)
{
result += db.Database.ExecuteSqlCommand(string.Format("DELETE FROM [{0}]", table));
db.Database.ExecuteSqlCommand(string.Format("DBCC CHECKIDENT ([{0}], RESEED, 0)", table));
}
scope.Complete();
}
return result;
}
public static List<string> GetTableList(this DbContext db)
{
var type = db.GetType();
return db.GetType().GetProperties()
.Where(x => x.PropertyType.Name == "DbSet`1")
.Select(x => x.Name).ToList();
}
}
이건 내게 효과가 있어요...EF v3.1.5
context.ModelName.RemoveRange(context.ModelName.ToList());
context.SaveChanges();
저는 제 몫을 기부하고 싶습니다.
저는 이 질문을 생각해 냈습니다. 이 질문은 저자가 요청한 것과 정확히 일치합니다.이것은.NET 5.
var query = "sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL; SET QUOTED_IDENTIFIER ON; DELETE FROM ?; ALTER TABLE ? CHECK CONSTRAINT ALL;'"
context.Database.ExecuteSqlRaw(query);
언급URL : https://stackoverflow.com/questions/6089403/delete-all-entities-in-entity-framework
'source' 카테고리의 다른 글
튜플 투 딕셔너리 목록 (0) | 2023.04.27 |
---|---|
Python 스크립트 내에서 UAC 권한 상승을 요청하시겠습니까? (0) | 2023.04.27 |
대규모 테이블에서 SQL Server 쿼리 성능 향상 (0) | 2023.04.27 |
Eclipse용 플러그인을 작성하는 방법은 무엇입니까? (0) | 2023.04.27 |
Ruby on Rails vs.의 경우 NET MVC 3.NET 가이? (0) | 2023.04.27 |