EF Core, DI, Шаблон репозитория и проблема с базовой структурой репозитория - PullRequest
2 голосов
/ 09 ноября 2019

У меня есть .net core rest api, который содержит гибридную структуру, в которой он содержит только репозитории, а не уровень обслуживания.

Теперь есть одна проблема, с которой я сталкиваюсь с базовым репозиторием и основной структурой. позвольте мне сначала объяснить проблему.

Итак, рассмотрим одну сущность. скажем, Продукт и ниже это определение для этой сущности. у этой сущности есть один базовый класс с именем FullAuditedEntity .

[Table(name: "Products")]
public class Product : FullAuditedEntity
{
    public string Name { get; set; }
}

public class FullAuditedEntity: IFullAuditedEntity
{
    public FullAuditedEntity() { }

    [Key]
    public virtual int Id { get; set; }
}

public interface IFullAuditedEntity
{
    int Id { get; set; }
}

Хранилище Base и его интерфейсы, как показано ниже.

public class EntityBaseRepository<T> : IEntityBaseRepository<T> where T : class, IFullAuditedEntity, new()
{
    private readonly ApplicationContext context;

    public EntityBaseRepository(ApplicationContext context)
    {
        this.context = context;
    }

    public virtual IEnumerable<T> items => context.Set<T>().AsEnumerable().OrderByDescending(m => m.Id);

    public virtual T GetSingle(int id) => context.Set<T>().FirstOrDefault(x => x.Id == id);
}

public interface IEntityBaseRepository<T> where T : class, new()
{
    IEnumerable<T> items { get; }
    T GetSingle(int id);
}

Итак, мой Хранилище продуктов будет таким.

public interface IProductRepository : IEntityBaseRepository<Product> { }

public class ProductRepository : EntityBaseRepository<Product>, IProductRepository
{
    private readonly ApplicationContext context;

    public ProductRepository(ApplicationContext context) : base(context: context)
    {
        this.context = context;
    }
}

Теперь, до этого момента все хорошо, я могу получить доступ к этому хранилищу в контроллерах и выполнять действия, перечисленные в базовом классе.

Проблема ЯСтолкнувшись: Итак, с этой структурой, если я попытаюсь добавить любую новую сущность без FullAuditedEntity (см. сущность Product выше, у меня там есть полностью аудируемая сущность базового класса), моя структура хранилища завершится сбоем и выдаст ошибку.

скажем, если я пытаюсь добавить новую сущность Реализация , и у этой новой сущности есть случайный идентификатор, поэтому я не хочу наследовать базовый класс FullAuditedEnitity. теперь в этом случае большая часть будет работать нормально, но когда я попытаюсь создать репозиторий для объекта реализации, он выдаст общую ошибку. см. ниже снимок этого.

enter image description here

То, что я пробовал до сих пор ...

Я думалсоздать параллельное базовое хранилище, которое не наследует FullAuditedEntity как универсальный класс, но я не уверен, что это лучший метод или нет. Также меня беспокоит то, что что, если я делаю какую-либо ошибку в моей нынешней структуре шаблона репозитория и внедрения зависимостей?

Любой мир помощи будет лучшим и действительно оцененным.

Заранее благодарим за ваше время.

1 Ответ

2 голосов
/ 11 ноября 2019

Репозитории обычно сопоставляются с таблицами базы данных. В таблице базы данных всегда должен быть какой-то столбец, который может однозначно идентифицировать строку в таблице, и обычно это столбец называют «Id». Таким образом, вы правильно реализовали FullAuditedEntity, так как существует свойство Id. Тем не менее, ваш Id всегда имеет тип int. Я предлагаю вам использовать следующую конструкцию, и тогда ваш Id будет иметь любой тип структуры, такой как int, decimal, Guid и т. Д .:

/// <summary>
/// Abstraction of the Entity
/// </summary>
public interface IEntity
{
    object Id { get; set; }        
}


/// <summary>
/// Base class for IDs
/// </summary>
public abstract class Entity<T>: IEntity where T: struct
{        
    public T Id { get; set; }

    object IEntity.Id
    {
        get { return Id; }
        set {                
            Id = (T)value;
        }
    }
}

public class EntityBaseRepository<T> : IEntityBaseRepository<T> where T : class, IEntity, new()
{ 
    // The code is omitted for the brevity
}

Кроме того, попробуйтечтобы избежать сущностей без Id, таких как Implementation, как в будущем, вам придется выяснить, как найти строки без Id в таблице базы данных.

ОБНОВЛЕНИЕ:

Если вы не хотите наследовать FullAuditedEntity, вы можете создать BaseRepository<T> и затем извлечь его в EntityBaseRepository.

public abstract class BaseRepository<T> : IEntityBaseRepository<T> where T : class, new()
{
    public virtual IEnumerable<T> items => throw new NotImplementedException();

    public virtual T GetSingle(int id)
    {            
        throw new NotImplementedException();
    }
}

public class EntityBaseRepository<T> : BaseRepository<T> where T : class
                                             , IFullAuditedEntity, new()
{
    public override IEnumerable<T> items => base.items;

    public override T GetSingle(int id)
    {
        return base.GetSingle(id);            
    }
}

, а затем в свой Implementation репозиторий:

public interface IImplementationRepository : IEntityBaseRepository<Implementation> { }


public class ImplementationRepository: BaseRepository<Implementation>
    , IImplementationRepository
{
    public override Implementation GetSingle(int id)
    {

        return base.GetSingle(id);
    }
}

ОБНОВЛЕНИЕ 1:

На мой взгляд, лучше использовать службы (Service layer), которые потребляют ITRepository<T>. Потому что это дает вам новые способности, такие как:

  1. Добавьте некоторые вычисления на данные, полученные репозиторием

  2. Переопределите ваши сущности, которые тянутРепозиторий

  3. Это еще один дополнительный слой развязки. Поэтому, когда вы редактируете свой сервисный слой, вам не нужно редактировать слой Repository, а затем перекомпилировать свою сборку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...