Изменение метода отчистки таблицы.

This commit is contained in:
2025-05-12 16:01:10 +04:00
parent 53baa87144
commit a9f9ae4b93
6 changed files with 113 additions and 181 deletions
+97
View File
@@ -0,0 +1,97 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
namespace Pf2eModel;
/// <summary>
/// Класс, обеспецивающий общий способ для отчистки данных таблиц.
///
/// Источник: https://www.codeproject.com/Articles/5339402/Delete-All-Rows-in-Entity-Framework-Core-6
/// </summary>
public static class EfCleanHelper
{
/// <summary>
/// Определение полного названия таблицы по служебному классу.
/// </summary>
/// <param name="entityType">Служебный класс, определяющий таблицу базы данных.</param>
/// <param name="defaultSchemaName">Схема таблицы по умолчанию (<c>"public"</c> для PostgresSQL)</param>
/// <returns></returns>
private static string GetName(IEntityType entityType, string defaultSchemaName = "public")
{
object? schema = entityType.FindAnnotation("Relational:Schema")?.Value;
string tableName =
entityType.GetAnnotation("Relational:TableName")?.Value?.ToString()
?? throw new($"Не могу определить название таблицы для типа {entityType}");
string schemaName = schema?.ToString() ?? defaultSchemaName;
string name = $"\"{schemaName}\".\"{tableName}\"";
return name;
}
/// <summary>
/// Определение полного названия таблицы по типу сущности.
/// </summary>
/// <typeparam name="T">Тип искомой сущности.</typeparam>
/// <param name="dbContext">Контекст, в котором производится поиск таблицы.</param>
/// <returns>Строковое представление названия таблицы.</returns>
public static string TableName<T>(DbContext dbContext)
where T : class
{
IEntityType entityType =
dbContext.Model.FindEntityType(typeof(T))
?? throw new($"Не могу определить название таблицы для класса {typeof(T)}");
return GetName(entityType);
}
/// <summary>
/// Определение полного названия таблицы по типу сущности.
/// </summary>
/// <typeparam name="T">Тип искомой сущности.</typeparam>
/// <param name="dbSet">CLR-представление таблицы, название которой требуется определить.</param>
/// <returns>Строковое представление названия таблицы.</returns>
public static string TableName<T>(DbSet<T> dbSet)
where T : class
{
IEntityType entityType = dbSet.EntityType;
return GetName(entityType);
}
/// <summary>
/// Отчистка содержимого таблицы.
/// </summary>
/// <typeparam name="T">Тип сущности, таблицу которой необходимо отчистить.</typeparam>
/// <param name="dbSet">CLR-представление таблицы, которую требуется отчистить.</param>
/// <returns>Строковое представление выполненной SQL-команды.</returns>
public static string Truncate<T>(this DbSet<T> dbSet)
where T : class
{
string cmd = $"TRUNCATE TABLE {TableName(dbSet)} CASCADE;";
DbContext context = dbSet.GetService<ICurrentDbContext>().Context;
context.Database.ExecuteSqlRaw(cmd);
return cmd;
}
/// <summary>
/// Получение SQL-команды отчистки содержимого всех таблиц базы данных.
/// </summary>
/// <param name="context">Контекст базы данных, в которой необходимо отчистить все строки.</param>
/// <returns>Строковое представление выполненных SQL-команды.</returns>
public static string TruncateAll(this DbContext context)
{
IEnumerable<IEntityType> tables = context.Model.GetEntityTypes();
List<string> cmdList = [];
foreach (IEntityType entityType in tables)
{
string cmd = $"TRUNCATE TABLE {GetName(entityType)} CASCADE;";
context.Database.ExecuteSqlRaw(cmd);
cmdList.Add(cmd);
}
return string.Join('\n', cmdList);
}
}
@@ -12,25 +12,6 @@ public partial class Function : Migration
{
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION f_truncate_tables()
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE
(SELECT 'TRUNCATE TABLE '
|| string_agg(format('%I.%I', schemaname, tablename), ', ')
|| ' CASCADE;'
FROM pg_tables
WHERE schemaname = 'public'
AND tablename != '__EFMigrationsHistory'
);
END
$func$;
"""
);
migrationBuilder.Sql(
"""
CREATE OR REPLACE FUNCTION f_drop_tables()
RETURNS void
LANGUAGE plpgsql AS
+6 -1
View File
@@ -52,7 +52,12 @@ public partial class Pf2eDbContext
private void BindEntity<T>(EntityTypeBuilder<T> entity)
where T : class, IEntity
{
entity.HasOne(e => e.Entity).WithOne().HasForeignKey<T>(e => e.Id).IsRequired();
entity
.HasOne(e => e.Entity)
.WithOne()
.HasForeignKey<T>(e => e.Id)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
/// <summary>