IExpression是Sql Artisan组件的条件描述接口,组件中使用的所有条件(包括组合条件)都是以IExpression体现出来。但现有版本中的IExpression只支持数据查询、删除和修改操作,对于聚合统计并没有直接支持,只能通过视图对象的方式来描述聚合统计;但这种方式需要描述实体使用不是很方便,因此产生对IExpression简化聚合统计的想法。接下来为大家介绍以外部扩展的方式对IExpression实现数据聚合统计功能。
通过接口规范聚合统计的功能:
/// <summary>
/// 数据统计描述接口
/// </summary>
public interface IStatistician
{
/// <summary>
/// 获取符合条件的记录数
/// </summary>
/// <returns>int</returns>
int CountOf();
/// <summary>
/// 获取符合条件的记录数
/// </summary>
/// <param name="session">数据库会话对象</param>
/// <returns>int</returns>
int CountOf(HFSoft.Data.IDataSession session);
/// <summary>
/// 符合条件的相关字段值求和
/// </summary>
/// <param name="field">求和字段对象</param>
/// <returns>object</returns>
object SumOf(FieldAdapter field);
/// <summary>
/// 符合条件的相关字段值求和
/// </summary>
/// <param name="field">求和字段对象</param>
/// <param name="session">数据库会话对象</param>
/// <returns>object</returns>
object SumOf(FieldAdapter field,IDataSession session);
/// <summary>
/// 符合条件的相关字段值求最大值
/// </summary>
/// <param name="field">求最大值字段对象</param>
/// <returns>object</returns>
object MaxOf(FieldAdapter field);
/// <summary>
/// 符合条件的相关字段值求最大值
/// </summary>
/// <param name="field">求最大值字段对象</param>
/// <param name="session">数据库会话对象</param>
/// <returns>object</returns>
object MaxOf(FieldAdapter field,IDataSession session);
/// <summary>
/// 符合条件的相关字段求最小值
/// </summary>
/// <param name="field">求最小值字段对象</param>
/// <returns>object</returns>
object MinOf(FieldAdapter field);
/// <summary>
/// 符合条件的相关字段求最小值
/// </summary>
/// <param name="field">求最小值字段对象</param>
/// <param name="session">数据库会话对象</param>
/// <returns>object</returns>
object MinOf(FieldAdapter field,IDataSession session);
/// <summary>
/// 符合条件的相关字段求平均值
/// </summary>
/// <param name="field">求平均值字段对象</param>
/// <returns>object</returns>
object AvgOf(FieldAdapter field);
/// <summary>
/// 符合条件的相关字段求平均值
/// </summary>
/// <param name="field">求平均值字段对象</param>
/// <param name="session">数据库会话对象</param>
/// <returns>object</returns>
object AvgOf(FieldAdapter field,IDataSession session);
}
制定行为接口后就实现相关接口的对象.因为明确统计的方式是基于条件的,所以接口实现类的默认构造函数必须具备IExpression参数对象。
/// <summary>
/// 数据统计处理对象
/// </summary>
public class StatisticianBuilder:IStatistician
{
/// <summary>
/// 构造指定条件的统计对象
/// </summary>
/// <param name="exp">条件对象</param>
public StatisticianBuilder(HFSoft.Data.Expressions.IExpression exp)
{
//
// TODO: 在此处添加构造函数逻辑
//
mExpression = exp;
}
private HFSoft.Data.Expressions.IExpression mExpression;
/// <summary>
/// 获取统计的条件
/// </summary>
public HFSoft.Data.Expressions.IExpression Expression
{
get
{
return mExpression;
}
}
#region IStatistician 成员
public int CountOf()
{
// TODO: 添加 StatisticianBuilder.CountOf 实现
if(ConnectionContext.SessionContext != null)
{
return ((IStatistician)this).CountOf(ConnectionContext.SessionContext);
}
else
{
using(IDataSession session = MappingContainer.ConfigContainer.OpenSession())
{
session.Open();
return ((IStatistician)this).CountOf(session);
}
}
}
int Statistician.IStatistician.CountOf(HFSoft.Data.IDataSession session)
{
object mValue = OnQuery(session,SqlMath.Count(new FieldAdapter("*",Expression.Table)));
if(mValue == null)
return 0;
return (int) mValue;
}
public object SumOf(HFSoft.Data.Mapping.FieldAdapter field)
{
// TODO: 添加 StatisticianBuilder.SumOf 实现
if(ConnectionContext.SessionContext != null)
{
return ((IStatistician)this).SumOf(field, ConnectionContext.SessionContext);
}
else
{
using(IDataSession session = MappingContainer.ConfigContainer.OpenSession())
{
session.Open();
return ((IStatistician)this).SumOf(field,session);
}
}
}
object Statistician.IStatistician.SumOf(HFSoft.Data.Mapping.FieldAdapter field, HFSoft.Data.IDataSession session)
{
// TODO: 添加 StatisticianBuilder.Statistician.IStatistician.SumOf 实现
return OnQuery(session,SqlMath.Sum(field.ToObjectField()));
}
public object MaxOf(HFSoft.Data.Mapping.FieldAdapter field)
{
// TODO: 添加 StatisticianBuilder.MaxOf 实现
if(ConnectionContext.SessionContext != null)
{
return ((IStatistician)this).MaxOf(field, ConnectionContext.SessionContext);
}
else
{
using(IDataSession session = MappingContainer.ConfigContainer.OpenSession())
{
session.Open();
return ((IStatistician)this).MaxOf(field,session);
}
}
}
object Statistician.IStatistician.MaxOf(HFSoft.Data.Mapping.FieldAdapter field, HFSoft.Data.IDataSession session)
{
// TODO: 添加 StatisticianBuilder.Statistician.IStatistician.MaxOf 实现
return OnQuery(session,SqlMath.Max(field.ToObjectField()));
}
public object MinOf(HFSoft.Data.Mapping.FieldAdapter field)
{
// TODO: 添加 StatisticianBuilder.MinOf 实现
if(ConnectionContext.SessionContext != null)
{
return ((IStatistician)this).MinOf(field,ConnectionContext.SessionContext);
}
else
{
using(IDataSession session = MappingContainer.ConfigContainer.OpenSession())
{
session.Open();
return ((IStatistician)this).MinOf(field,session);
}
}
}
object Statistician.IStatistician.MinOf(HFSoft.Data.Mapping.FieldAdapter field, HFSoft.Data.IDataSession session)
{
// TODO: 添加 StatisticianBuilder.Statistician.IStatistician.MinOf 实现
return OnQuery(session, SqlMath.Min(field.ToObjectField()));
}
public object AvgOf(HFSoft.Data.Mapping.FieldAdapter field)
{
// TODO: 添加 StatisticianBuilder.AvgOf 实现
if(ConnectionContext.SessionContext != null)
{
return ((IStatistician)this).AvgOf(field,ConnectionContext.SessionContext);
}
else
{
using(IDataSession session = MappingContainer.ConfigContainer.OpenSession())
{
session.Open();
return ((IStatistician)this).AvgOf(field,session);
}
}
}
object Statistician.IStatistician.AvgOf(HFSoft.Data.Mapping.FieldAdapter field, HFSoft.Data.IDataSession session)
{
// TODO: 添加 StatisticianBuilder.Statistician.IStatistician.AvgOf 实现
return OnQuery(session,SqlMath.Avg(field.ToObjectField()));
}
#endregion
private object OnQuery(IDataSession session ,params FieldAdapter[] fields)
{
IQuery query = session.CreateQuery(Expression.Table);
query.Selects = fields;
query.Expreesion = Expression;
using(IDataReader reader = query.ExecuteReader())
{
if(reader.Read())
return reader[0];
}
return null;
}
}
就以上两步就已经完成IExpression对聚合统计支持的扩展。接下来看一下扩展后的使用效果:
//实例订单日期在1997-1-1之后的统计对象
IStatistician stat = new StatisticianBuilder(
DBMapping.Orders.OrderDate > DateTime.Parse("1997-1-1"));
//统计所有记录数
stat.CountOf();
//实例订单日期在1997-1-1之后的销售明细统计对象
stat = new StatisticianBuilder(
DBMapping.OrderDetails.Order==(DBMapping.Orders.OrderDate > DateTime.Parse("1997-1-1"))
);
//统计销售产品总和
stat.SumOf(DBMapping.OrderDetails.Quantity);
//统计销售产品的平均价格
stat.AvgOf(DBMapping.OrderDetails.UnitPrice);
因为以上扩展并没有改变IExpression的任何实现,因此并不能完全基于条件驱动的方式进行操作,必须借助于StatisticianBuilder来进行整合和处理。当修改IExpression继承 IStatistician接口就能发挥基于条件驱动的简便操作方式。同样以上扩展的聚合统计并不支持分组,因为分组返回的结果是多成员的,所以通过视图对象描述会比较合理。