繁体   English   中英

具有继承的通用存储库问题

[英]Generic repository issue with inheritance

我在 .Net 中有 N 层解决方案,使用 PetaPoco 作为 microORM。 我得到了从 PetaPoco 的模板生成器生成的实体。 这些实体T派生自基类Record<T> 然后我扩展它们,添加更多数据访问工具和自定义Save()Delete()方法,它们覆盖Record<T>默认方法。

以下是实体中覆盖的Delete方法(我要调用的方法)

public partial class Document : Record<Document>
{
    public new int Delete()
    {
        int rowsAffected;
        using (var uow = DB.GetInstance().GetTransaction())
        {
            rowsAffected = base.Delete();
            LogSystem("Deleting", "Deleting a document", 0, 0, GUID);
            uow.Complete();
        }
        return rowsAffected;
    }
}

然后,当我创建通用存储库时,调用的方法来自基类Record<T>而不是来自实体的自定义方法。 当我调用entityRepository.Delete()方法时,应调用实体中的Delete()方法,而不是默认Record<T>类中的方法。

通用存储库类如下:

public abstract class GenericRepository<T> : IGenericRepository<T> where T : Record<T>, new()
{
    public void Delete(T entity)
    {
        entity.Delete();
    }
}

忏悔:我对 PetaPoco 及其模板生成器一无所知。

与 PetaPoco 恕我直言相比,该问题与 OO(特别是继承)更相关。 如果使用Record<T>创建通用存储库,它也是每个实体的基类,那么发生的事情正如预期的那样。 您需要仔细研究类的继承。

您可能需要对我在下面提出的解决方案进行一些更改以匹配 ORM 功能。

解决方案1:

声明一个新的基类或接口,如下所示:

public interface IEntityBase{.....

在接口中包含必要的成员,如Delete方法。

然后,也从这个接口派生每个实体:

public partial class Document : Record<Document>, IEntityBase

然后,创建这个接口,而不是一个通用的存储库Record<T>类似下面:

public abstract class GenericRepository<T> : IGenericRepository<T> where T : IEntityBase

这样,您无需更改现有代码即可实现目标。

解决方案2:

另一个肮脏的解决方案是将Record<T>为它的实际实例。

public void Delete(T entity)
{
    if(typeof(T) == typeof(Document))
        Document myEntity = (Document)entity;
    myEntity.Delete();
}

在每种方法中进行铸造绝对是个坏主意。 在您的代码中寻找一些更好的集中位置。 我只是想给你指路。

解决方案3:

其他想法是使Record<T>Delete方法成为virtual方法。 但我不确定你的 ORM 是如何工作的,或者你的 ORM 是否允许这样做,所以我不会对此发表评论。

此问题的原因是在您的GenericRepository您将 T 指定为“从 Record 派生的东西”。 因此,调用entity.Delete() ,此调用将链接到此基本方法,因为这仅对 T 的所有可能实例执行一次。

如果您有权访问Record<T>类,只需将Delete()方法设为虚拟并在Document覆盖它。

如果没有,请尝试使用以下内容:

public class ExtendedRecord<T>: Record<T>
{
  public virtual new int Delete()
  {
    base.Delete();
  }
}

public partial class Document : ExtendedRecord<Document>
{
  public override int Delete()
  {
    // ...
  }
}

public abstract class GenericRepository<T> : IGenericRepository<T>
  where T : ExtendedRecord<T>, new()
{
  // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM