自定义可绑定数据的业务对象实体和强类型-Part Three
步骤二 : 创建自定义业务层
第一件要做的事情,就是添加一个新的工程文件到我们的解决方案中,再次,它的类型是一个类库,命名为"DCAF.BusinessLayer".
因为我们的自定义业务对象应该被告知去哪里取他们的数据,因为这一点,我们应该添加一个到DCAF.DataLayer集合的引用.这个可以简单地通过在工程文件夹中选择"引用",然后右击,选择"添加引用",转到"工程(译注:俺的IDE版本显示的是'项目')"页签,选择图6所示的集合.
图6.添加集合引用到工程中
下一步,添加两个类到工程中,命名为"CustomerBO"(持有Customer的定义)和"OrderBO"(持有Order的定义).
using System.Collections.Generic;
using System.Text;
using DCAF.DataLayer;
using DCAF.DataLayer.CustomerOrderTDSTableAdapters;
namespace DCAF.BusinessLayer
{
public class CustomerBO
{
private string m_CustomerId;
private string m_CompanyName;
private List<OrderBO> m_Orders = new List<OrderBO>();
public string CustomerId
{
get { return m_CustomerId; }
set { m_CustomerId = value; }
}
public string CompanyName
{
get { return m_CompanyName; }
set { m_CompanyName = value; }
}
public List<OrderBO> Orders
{
get { return m_Orders; }
}
}
}
顾客业务对象类包含2个属性,一个是它的ID,一个是它的Name,一个存储订单(列表)的集合.同时注意到这里DCAF.DataLayer的引用,我们会在一分钟内返回来这里.
using System.Collections.Generic;
using System.Text;
namespace DCAF.BusinessLayer
{
public class OrderBO
{
private int m_OrderId;
private string m_ProductName;
private CustomerBO m_Customer;
private DateTime m_OrderDate;
public int OrderId
{
get { return m_OrderId; }
set { m_OrderId = value; }
}
public string ProductName
{
get { return m_ProductName; }
set { m_ProductName = value; }
}
public CustomerBO Customer
{
get { return m_Customer; }
set { m_Customer = value; }
}
public DateTime OrderDate
{
get { return m_OrderDate; }
set { m_OrderDate = value; }
}
}
}
另一方面,订单表也包含了一些属性值和一个指向它所属的顾客的引用.
最后...我们应该实现我们的O/R映射功能,用数据来填实我们的顾客业务对象!为此,我已经实现了另一个方法(代码部分的下面有解释).方法应该被添加到CustomerBO类中!
{
//--- Create the DataService
CustomerOrderService dataService = new CustomerOrderService();
CustomerOrderTDS dataContainer;
dataContainer = new CustomerOrderTDS();
//--- Create the DataContainer for Customers and Orders retrieval
dataContainer.Merge(dataService.GetCustomerOrders());
//--- Create a CustomerObject List to hold the Customers
List<CustomerBO> customerList = new List<CustomerBO>();
//--- Loop through the CustomerData from our DataContainer
foreach (CustomerOrderTDS.CustomersRow customerRow in dataContainer.Customers.Rows)
{
//--- Create a Customer Object Instance
CustomerBO customer = new CustomerBO();
//--- Map the Relational data to Object properties
//for Customer
ORM.RelationalToObject(customer, customerRow);
//--- Select the Related Orders of the Customer
CustomerOrderTDS.OrdersRow[] orderRows =
(CustomerOrderTDS.OrdersRow[])customerRow.GetChildRows("FK_Orders_Customers");
//--- Loop through the related OrderData for the
// Current Customer
int numOrder = 0;
foreach (CustomerOrderTDS.OrdersRow orderRow in orderRows)
{
numOrder++;
//--- Create an Order Object Instance
OrderBO order = new OrderBO();
//--- Map the Relational data to Object
//properties for Order
ORM.RelationalToObject(order, orderRow);
//--- Add the Customer Reference to the Order
order.Customer = customer;
order.ProductName = string.Format("Product {0}-{1}", order.OrderId, numOrder);
//--- Relate the Order to The Current Customer
customer.Orders.Add(order);
}
customerList.Add(customer);
}
return customerList;
}
因此,我们创建一个叫做"GetCustomerOrders"的静态方法,返回一个顾客对象列表(注意:你也可以使用List的泛型匹配,List<T>).首先,我们通过我们的强类型中的数据服务抓取数据.然后,我们循环遍历Customer的数据容器行,添加Customer信息,为Orders得到子行,添加Order信息,最后,添加Customer对象到List中.
为了简化O/R映射任务,我已经添加一个ORM类到工程中.该类有两个方法,一个用于映射关系数据到对象属性(叫做ORM.RelationalToObject),另一个用于保持对象时将属性映射回关系数据,这是一个动态的方式,因此,这两个方法可以在任何"表/对象"(table/object)映射的场景.下面的代码演示了RelationalToObject映射方法.相反的方法将在我们描述我们的保持程序时解释.
{
//--- Get Object Properties
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(p_obj);
//--- Apply OR-Mapping
foreach (DataColumn column in p_dataRow.Table.Columns)
{
for (int propertyIndex = 0; propertyIndex < props.Count; propertyIndex++)
{
PropertyDescriptor prop;
try
{
prop = props[propertyIndex];
}
catch
{
continue;
}
//--- Omit IListTypes (childcollections)
if (prop.PropertyType.GetInterface("IList") == null)
{
if (prop.Name.Trim().ToLower() == column.ColumnName.Trim().ToLower())
{
prop.SetValue(p_obj, p_dataRow[column]);
}
}
}
}
}
我们已经完成了业务层(BusinessLayer),值得提的是,正是为了该演示,我遵循一个非常基本的业务对象(BusinessObject)的部署规则,没有考虑到业务规则(BizzRules),缓存,属性修改消息(将在描述Save()部分时涉及)等等,因为那些部署已经超出本文的范围.