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。
我写了一个具体的 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。