Язык программирования C#9 и платформа .NET5
Шрифт:
public abstract class BaseRepo<T> : IRepo<T> where T : BaseEntity, new
Классу хранилища нужен экземпляр
ApplicationDbContext
, внедренный через конструктор. В случае использования с контейнером внедрения зависимостей ASP.NET Core временем жизни контекста будет управлять контейнер. Второй конструктор будет принимать DbContextOptions
и должен создавать экземпляр ApplicationDbContext
, который понадобится освобождать. Поскольку этот класс является абстрактным, оба конструктора определяются как защищенные. Добавьте в открытый класс ApplicationDbContext
private readonly bool _disposeContext;
public ApplicationDbContext Context { get; }
protected BaseRepo(ApplicationDbContext context)
{
Context = context;
_disposeContext = false;
}
protected BaseRepo(DbContextOptions<ApplicationDbContext> options) : this(new
ApplicationDbContext(options))
{
_disposeContext = true;
}
public void Dispose
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _isDisposed;
protected virtual void Dispose(bool disposing)
{
if (_isDisposed)
{
return;
}
if (disposing)
{
if (_disposeContext)
{
Context.Dispose;
}
}
_isDisposed = true;
}
~BaseRepo
{
Dispose(false);
}
На свойства
DbSet<T>
класса ApplicationDbContext
можно ссылаться с использованием метода Context.Set<T>
. Создайте открытое свойство по имени Table
типа DbSet<T>
и установите его начальное значение в конструкторе:
public DbSet<T> Table { get; }
protected BaseRepo(ApplicationDbContext context)
{
Context = context;
Table = Context.Set<T>;
_disposeContext = false;
}
Реализация метода SaveChanges
Класс
BaseRepo
имеет метод SaveChanges
, который вызывает переопределенную версию SaveChanges
и демонстрирует обработку специальных исключений. Добавьте в класс BaseRepo
показанный ниже код:
public int SaveChanges
{
try
{
return Context.SaveChanges;
}
catch (CustomException ex)
{
//
Подлежит надлежащей обработке -- уже зарегистрировано в журнале.
throw;
}
catch (Exception ex)
{
// Подлежит регистрации в журнале и надлежащей обработке.
throw new CustomException("An error occurred updating the database", ex);
}
}
Реализация общих методов чтения
Следующий комплект методов возвращает записи с применением операторов LINQ. Метод
Find
принимает первичный ключ (ключи) и сначала выполняет поиск в ChangeTracker
. Если сущность уже отслеживается, тогда возвращается отслеживаемый экземпляр, иначе запись извлекается из базы данных.
public virtual T? Find(int? id) => Table.Find(id);
Дополнительные два метода
Find
расширяют базовый метод Find
. Приведенный далее метод демонстрирует извлечение записи, но без ее добавления в ChangeTracker
, используя AsNoTrackingWithldentityResolution
. Добавьте в класс показанный ниже код:
public virtual T? FindAsNoTracking(int id) =>
Table.AsNoTrackingWithIdentityResolution.FirstOrDefault(x => x.Id == id);
Другая вариация удаляет из сущности фильтры запросов и затем применяет сокращенную версию (пропускающую метод
Where
) для получения FirstOrDefault
. Добавьте в класс следующий код:
public T? FindIgnoreQueryFilters(int id) =>
Table.IgnoreQueryFilters.FirstOrDefault(x => x.Id == id);
Методы
GetAll
возвращают все записи из таблицы. Первый метод извлекает их в порядке, поддерживаемом в базе данных, а второй по очереди обрабатывает все фильтры запросов:
public virtual IEnumerable<T> GetAll => Table;
public virtual IEnumerable<T> GetAllIgnoreQueryFilters
=> Table.IgnoreQueryFilters;
Метод
ExecuteQuery
предназначен для выполнения хранимых процедур:
public void ExecuteQuery(string sql, object[] sqlParametersObjects)
=> Context.Database.ExecuteSqlRaw(sql, sqlParametersObjects);
Реализация методов добавления, обновления и удаления
Далее понадобится добавить блок кода, который будет служить оболочкой для соответствующих методов добавления, обновления и удаления, связанных со специфичным свойством
DbSet<T>
. Параметр persist
определяет, выполняет ли хранилище вызов SaveChanges
сразу же после вызова методов добавления, обновления и удаления. Все методы помечены как virtual
, чтобы сделать возможным дальнейшее переопределение. Добавьте в класс показанный ниже код:
Поделиться с друзьями: