我有.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 基类。现在在这种情况下,大多数事情都会正常工作,但是当我尝试为实现实体创建存储库时,它将给出一般错误。请参阅下面的快照。
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>
) 。
因为它赋予您新的能力,例如:
对Repository获取的数据添加一些计算
重新映射存储库拉取的实体
这是额外的一层解耦。因此,当您编辑服务层时,您不需要编辑存储库层,然后重新编译程序集
关于c# - EF Core、DI、存储库模式和基本存储库结构的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58777203/