表模块和领域模型比,有两个显著区别:
1:表模块中的类和数据库表基本一一对应,而领域模型则无此要求;
2:表模块中的类的对象处理表中的所有记录,而领域模型的一个对象代表表中的一行记录;
一般情况下,我们可以基于第二点来严格区分你的设计是表模块的,还是领域模型的。如:如果我们有许多订单,则领域模型的每一个订单都有一个对象,而表模块只有一个对象来处理所有订单(注意,这里的类,都是指业务逻辑层的类,而不是实体类。表模块的类的对象和常规的领域模型的对象很类似,但是关键区别是:它没有标识符来标出它所代表的实体对象)。举例来说,如果要查询某个订单,表模块会像这样进行编码:
anOrderModule.GetOrder(string orderId);
因为表模块只有一个对象来处理所有订单,所以表模块可以是一个实例,也可以是一个只包含静态方法的静态类。
表模块 的代码和 事务脚本类似:
class TableModel
{
protected DataTable table;
protected TableModel(DataSet ds, string tableName)
{
table = ds.Tables[tableName];
}
}class Contract : TableModel
{
public Contract(DataSet ds) : base (ds, "Contracts")
{
}
public DataRow this[long id]
{
get
{
string filter = "ID=" + id;
return table.Select(filter)[0];
}
}
public void CalculateRecognitions(long contactId)
{
DataRow contractRow = this[contactId];
double amount = (double)contractRow["amount"];
RevenueRecognition rr = new RevenueRecognition(table.DataSet);
Product prod = new Product(table.DataSet);
long prodId = GetProductId(contactId);
if(prod.GetProductType(prodId) == "W")
{
rr.Insert(contactId, amount, (DateTime)GetWhenSigned(contactId));
}else if(prod.GetProductType(prodId) == "S") // 电子表格类
{
// the sql "INSERT INTO REVENUECONGNITIONS (CONTRACT,AMOUNT,RECOGNIZEDON) VALUES (?,?,?)"
DateTime dateSigned = (DateTime)GetWhenSigned(contactId);
rr.Insert(contactId, amount / 3, dateSigned);
rr.Insert(contactId, amount / 3, dateSigned.AddDays(60));
rr.Insert(contactId, amount / 3, dateSigned.AddDays(90));
}else if(prod.GetProductType(prodId) == "D") // 数据库
{
DateTime dateSigned = (DateTime)GetWhenSigned(contactId);
rr.Insert(contactId, amount / 3, dateSigned);
rr.Insert(contactId, amount / 3, dateSigned.AddDays(30));
rr.Insert(contactId, amount / 3, dateSigned.AddDays(60));
}
}
private long GetProductId(long contactId)
{
return (long)this[contactId]["ProductId"];
}
private DateTime GetWhenSigned(long contactId)
{
return (DateTime)this[contactId]["DateSigned"];
}
}class RevenueRecognition : TableModel
{
public RevenueRecognition(DataSet ds) : base (ds, "RevenueRecognitions")
{
}
public long Insert(long contactId, double amount, DateTime whenSigned)
{
DataRow newRow = table.NewRow();
long id = GetNextId();
newRow["Id"] = id;
newRow["ContactId"] = contactId;
newRow["Amount"] = amount;
newRow["DateSigned"] = whenSigned;
table.Rows.Add(newRow);
return id;
}
// 得到哪天前入账了多少
public double RecognizedRevenue(long contractNumber, DateTime asOf)
{
// the sql "SELECT AMOUNT FROM REVENUECONGNITIONS WHERE CONTRACT=? AND RECOGNIZEDON <=?";
string filter = string.Format("ContactId={0} AND date <=#{1:d}", contractNumber, asOf);
DataRow[] rows = table.Select(filter);
double r = 0.0;
foreach(DataRow dr in rows)
{
r += (double)dr["AMOUNT"];
}
return r;
}
private long GetNextId()
{
throw new Exception();
}
}class Product : TableModel
{
public Product(DataSet ds) : base (ds, "Products")
{
}
public DataRow this[long id]
{
get
{
string filter = "ID=" + id;
return table.Select(filter)[0];
}
}
public string GetProductType(long productId)
{
return (string)this[productId]["Type"];
}
}
架构模式逻辑层模式之:表模块(Table Model)