Чтение онлайн

ЖАНРЫ

Язык программирования 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
, чтобы сделать возможным дальнейшее переопределение. Добавьте в класс показанный ниже код:

Поделиться с друзьями: