Мой вопрос заключается в использовании внедрения зависимостей в .NET Core. Я могу создавать разные репозитории для некоторых операций CRUD и предоставлять их API. Однако, делая это так, как показано ниже, я получаю много повторяющегося кода, поскольку мне приходится создавать новые методы для добавления, обновления и удаления для каждого класса. Как я могу это сделать, но имея для этого общий код, поскольку единственные вещи, которые действительно меняются, - это сущности и используемая таблица. Вы также можете увидеть тот же код на .NET Fiddle.
Я удалил как можно больше несущественного кода...
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public interface IBaseDao
{
Task SaveChangesAsync(CancellationToken cancellationToken);
}
public interface ICrudRepository<TModel, TId> : IBaseDao
{
public Task<TModel> AddAsync(TModel model, CancellationToken cancellationToken);
public Task<TModel> UpdateAsync(TModel model, CancellationToken cancellationToken);
public Task DeleteAsync(TId id, string userName, CancellationToken cancellationToken);
}
public interface IPersonCrudRepository : ICrudRepository<Person, int>
{
}
public abstract class BaseDao : IBaseDao
{
protected BaseDao(CustomDbContext dbContext) =>
this.CustomDbContext = dbContext;
protected CustomDbContext CustomDbContext { get; set; }
public virtual async Task SaveChangesAsync(CancellationToken cancellationToken) =>
_ = await this.CustomDbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}
public class CustomDbContext : DbContext
{
public CustomDbContext(DbContextOptions<CustomDbContext> options)
: base(options)
{
}
}
public class PersonCrudRepository : BaseDao, IPersonCrudRepository
{
public PersonCrudRepository(CustomDbContext dbContext)
: base(dbContext)
{
}
public async Task<Person> AddAsync(Person model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
var entity = (await this.CustomDbContext
.Set<Person>()
.AddAsync(model, cancellationToken)
.ConfigureAwait(false)).Entity;
await this.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
return entity;
}
public async Task DeleteAsync(int id, string userName, CancellationToken cancellationToken)
{
var entity = new Person { Id = id };
_ = this.CustomDbContext.Set<Person>().Attach(entity);
entity.ModifiedBy = userName;
entity.StatusId = (byte)Status.Inactive;
await this.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}
public async Task<Person> UpdateAsync(Person model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
_ = this.CustomDbContext.Set<Person>().Attach(model);
await this.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
return model;
}
}
public class Person : ChangeTracker
{
public int Id { get; set; }
public string Name { get; set; } = default!;
}
public abstract class ChangeTracker
{
public string ModifiedBy { get; set; }
public byte StatusId { get; set; }
}
public enum Status
{
Active = 1,
Inactive = 2,
}
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
{
}
public virtual void ConfigureServices(IServiceCollection services) =>
_ = services.AddScoped<IPersonCrudRepository, PersonCrudRepository>();
}
Помогает ли ответ по этой ссылке? stackoverflow.com/questions/68273081/abstract-database-access/…





Вы можете сделать что-то общее ->
//создаем общий интерфейс
public interface IBaseRepository<T>
{
public IQueryable<T> GetAll();
public T? GetById(Guid id);
public Task<T?> GetByIdAsync(Guid id);
public IQueryable<T> GetByCondition(Expression<Func<T, bool>> expression);
public void Create(T entity);
public Task CreateAsync(T entity);
public void Update(T entity);
public void Delete(T entity);
public void Save();
public Task SaveAsync();
}
//создаем универсальный абстрактный класс
public abstract class BaseRepository<T> : IBaseRepository<T> where T : class
{
protected readonly CustomDbContext _dbContext;
protected BaseRepository(CustomDbContext dbContext)
{
_dbContext = dbContext;
}
public IQueryable<T> GetAll() => _dbContext.Set<T>().AsNoTracking();
public T? GetById(Guid id) => _dbContext.Set<T>().Find(id);
public async Task<T?> GetByIdAsync(Guid id) => await _dbContext.Set<T>().FindAsync(id);
public IQueryable<T> GetByCondition(Expression<Func<T, bool>> expression) => _dbContext.Set<T>().Where(expression);
public void Create(T entity) => _dbContext.Set<T>().Add(entity);
public async Task CreateAsync(T entity) => await _dbContext.Set<T>().AddAsync(entity);
public void Update(T entity) => _dbContext.Set<T>().Update(entity);
public void Delete(T entity) => _dbContext.Set<T>().Remove(entity);
public void Save() => _dbContext.SaveChanges();
public async Task SaveAsync() => await _dbContext.SaveChangesAsync();
}
//создаем интерфейс репозитория
public interface IExampleRepository : IBaseRepository<ExampleEntityClass>
{
}
// создайте свой конкретный класс репозитория
public class Repository : BaseRepository<ExampleEntityClass>, IExampleRepository
{
public Repository (CustomDbContext dbContext) : base(dbContext)
{
}
}
я думаю, что это хорошее решение, я бы изменил методы и объявил их виртуальными, на всякий случай, если какой-либо из них нуждается в альтернативной реализации.
Это был правильный ответ для моих нужд. Я поделился своими изменениями на .NET Fiddle
Вы думали об универсальном абстрактном классе? когда я работал с dapper, я просто решил это таким образом, другим подходом были бы методы расширения