Returns C# 中的泛型数据库结果集

Returns Generic type Database result set in C#

我写了一个具体的 class 来公开数据库结果集,其中包括 T 型列表项和总行数。看了一些(依赖倒置原则,接口隔离原则),我发现它应该暴露为接口而不是具体的class。

这是我的代码,最好的写法是什么 class 公开为 IDbResultSet 而不是公开为 DbResultSet.

public class DbResultSet<T>
{
    public List<T> Items { get; private set; }
    public int TotalRowCount { get; private set; }

    public DbResultSet(List<T> items, int totalRowCount)
    {
        this.Items = items;
        this.TotalRowCount = totalRowCount;
    }
}

用法:

DbResultSet<Category> GetCategory(int categoryId);

你无能为力。只是设计界面而已:

public interface IDbResultSet<T, TCollection>
       where TCollection : ICollection<T>
{
     TCollection Items { get; }
     int TotalRowCount { get; }
}

正如您在上面所看到的,整个接口没有定义 Items 集合类型:它可以是任何实现 ICollection<T>.

的集合

现在您可以按如下方式实现:

public class DbResultSet<T, TCollection> : IDbResultSet<T, TCollection>
       where TCollection : ICollection<T> 
{
    public TCollection  Items { get; private set; }
    public int TotalRowCount { get; private set; }

    public DbResultSet(TCollection items, int totalRowCount)
    {
        // Note that qualifying with "this" is redundant here
        // so I've removed it
        Items = items;
        TotalRowCount = totalRowCount;
    }
}

顺便说一句,我建议您将界面和 class 名称从 ResultSet 更改为 Result 原样 ,因为 set 是一种集合类型,没有顺序,但集合项是 unique:

public interface IDbResult<T, TCollection>
       where TCollection : ICollection<T>
{
     TCollection Items { get; }
     int TotalRowCount { get; }
}

public class DbResult<T, TCollection> : IDbResultSet<T, TCollection>
       where TCollection : ICollection<T> 
{
    public TCollection  Items { get; private set; }
    public int TotalRowCount { get; private set; }

    public DbResult(TCollection items, int totalRowCount)
    {
        // Note that qualifying with "this" is redundant here
        // so I've removed it
        Items = items;
        TotalRowCount = totalRowCount;
    }
}

因此,您可以公开类型为接口类型的结果:

IDbResult<Category, IList<Category>> GetCategories();

一些建议

我看到您甚至想对 单个结果使用该方法:

 DbResultSet<Category> GetCategory(int categoryId);

我的建议是您应该将结果分成两个家族

  • 单一结果。
  • 多个结果。

所以我最终会得到这些接口:

public interface IMultipleDbResult<T, TCollection>
       where TCollection : ICollection<T>
{
     TCollection Items { get; }
     int TotalRowCount { get; }
}

public interface ISingleDbResult<T>
{
      T Item { get; }
}

我建议你这样做是因为奇怪的是你知道你正在通过 Id 获得 一个类别并且你可能需要从列表中获取它:

IDbResult<Category, IList<Category>> result = GetCategoryById(389);
Category category = result.Items[0]; // ??????

// vs.

ISingleDbResult<Category> result = GetCategoryById(389);
Category category = result.Item; // Isn't it more elegant?

顺便说一句,我知道您的实际解决方案涉及在两种结果类型上实现更多属性。例如收集数据库查询错误信息或其他有用的数据。

另一方面,我猜您正在实施 TotalRowCount 之类的 属性,因为您正在对结果进行分页。例如,可能有 300 个类别,但 Items 属性 包含第一页的 10 个项目。否则,您的推理有一些缺陷,因为 ICollection<T> 的所有实现都已经拥有 Count 属性.

最后,也许对我在网上发布的一些设计模式感兴趣。参见 Accmulated Result design pattern