c# - EF Core、DI、存储库模式和基本存储库结构的问题

标签 c# dependency-injection repository-pattern asp.net-core-2.1 ef-core-2.1

我有.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; }
}

基础存储库及其接口(interface)如下。

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;
    }
}

现在,到目前为止一切都很好,我可以在 Controller 中访问此存储库并可以执行基类中列出的操作。

Issue I am facing : So with this structure, If I tries to add any new entity without FullAuditedEntity (see Product entity above, I have base class full audited entity over there), my structure of repository fails and it gives error.

假设我尝试添加新实体Implementation,并且这个新实体具有随机 ID,因此我不想继承 FullAuditedEnitity 基类。现在在这种情况下,大多数事情都会正常工作,但是当我尝试为实现实体创建存储库时,它将给出一般错误。请参阅下面的快照。

enter image description here

What I tried so far...

我正在考虑创建一个并行的基本存储库,它不继承 FullAuditedEntity 作为通用类,但我不确定这是否是最佳实践。我还担心如果我在当前的存储库模式和依赖注入(inject)结构中犯了任何错误怎么办?

任何帮助世界变得最好的东西,我们都非常感激。

提前感谢您抽出时间。

最佳答案

存储库通常映射到数据库表。数据库表应该始终有一些可以唯一标识表中行的列,通常的做法是将此列称为 Id 。所以你正确地实现了你的 FullAuditedEntity因为有 Id属性(property)。然而,你的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. 对Repository获取的数据添加一些计算

  2. 重新映射存储库拉取的实体

  3. 这是额外的一层解耦。因此,当您编辑服务层时,您不需要编辑存储库层,然后重新编译程序集

关于c# - EF Core、DI、存储库模式和基本存储库结构的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58777203/

相关文章:

c# - 如何循环 Console.ReadLine?

c# - .NET Reflector 和 getters/setters 问题

php - Laravel ioc 自动解析 - 从 Controller 工作但不是从自定义类工作

asp.net-mvc - 在 MVC Web 应用程序中跨存储库共享 DbContext

c# - 如何找到数组中的最大差异

c# - 无法理解如何在单元测试中使用 Mock

c# - 是否有用于 WinForm 的 Autofac 集成库

.net - 我应该在 dotnet 中使用哪种依赖注入(inject)技术?

c# - DI Framework : how to avoid continually passing injected dependencies up the chain, 且未使用服务定位器(特别是使用 Ninject)

asp.net - Entity Framework asp.net 应用程序中的 UOW 和存储库