petapoco的{.net通用存储库问题

时间:2017-10-26 13:43:12

标签: c# generics repository-pattern data-access-layer petapoco

我在.Net中使用PetaPoco作为microORM的N层解决方案。我得到了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();
    }
}

2 个答案:

答案 0 :(得分:0)

  

忏悔:我不了解PetaPoco及其模板生成器。

与PetaPoco恕我直言相比,问题与OO(特别是继承)有关。如果使用Record<T>创建通用存储库,public interface IEntityBase{..... 也是每个实体的基类,那么发生的事情就像预期的那样。您需要密切关注类的继承。

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

解决方案1:

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

Delete

在界面中包含必要的成员,例如public partial class Document : Record<Document>, IEntityBase 方法。

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

Record<T>

然后,使用此界面创建一个通用存储库,而不是像public abstract class GenericRepository<T> : IGenericRepository<T> where T : IEntityBase 那样,如下所示:

Record<T>

这样,您就可以在不改变现有代码的情况下实现目标。

解决方案2:

另一个解决方案是将public void Delete(T entity) { if(typeof(T) == typeof(Document)) Document myEntity = (Document)entity; myEntity.Delete(); } 转换为其实际实例。

Delete

在每种方法中进行投射绝对是个坏主意。在代码中寻找更好的集中位置。我只是想告诉你的方式。

解决方案3:

其他想法是在Record<T> virtual方法中制作//Prepare the response $numberOfPages = ceil( $numberOfRows / $rowsPerPage ); 方法。但我不确定你的ORM是如何工作的,或者即使你的ORM允许这样做,所以我不会对此发表评论。

答案 1 :(得分:0)

此问题的原因在于,在GenericRepository中,您将T指定为&#34;从Record&#34;中获取的内容。所以wenn调用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()
{
  // ...
}