自定义可绑定数据的业务对象实体和强类型-Part Five
对数据库做增,删,改操作
至今,我们已经添加代码,从数据层(DataLayer)绑定数据到表现层中的数据绑定控件(DataGridView).这里,用户可以添加,删除或者修改Customer或者Order相关数据,通过DataGridView提供的界面接口.经过添加,删除或者修改数据后,用户可以选择更新输入的信息到数据库中.在本篇剩下的部分,我们将描述有关的必要的步骤,怎么用新的,修改的或者删除的数据区更新数据库.
这里缺少一些相关的代码,来更新我们的Customer对象到数据层(DataLayer),首先,我们将添加两个List实例,做为我们Customer管理窗体的私有成员.这些List实例将保持明确删除的Customers和Orders.
private List<CustomerBO> m_deletedCustomers = null; 
private List<OrderBO> m_deletedOrders = null;
下一步,我们应该处理customerBOBindingSource的AddingNew事件,为BindingSource处理一个新的Customer对象的添加(如图19).
图19.处理CustomerBindingSource的AddingNew事件
处理添加一个新Customer到我们的CustomerBindingSource的代码,如下所示.
private void customerBOBindingSource_AddingNew(object sender, AddingNewEventArgs e)
{
CustomerBO customer = new CustomerBO();
customer.IsNew = true;
customer.IsDirty = true; 
customer.CompanyName = "[新客户名]";
customer.CustomerId = "[新客户ID]"; 
e.NewObject = customer;
customer = null;
} 相同的事件处理过程应该被激活,为我们的OrderBindingSource.注意(看下面的代码)到,用于添加一个新订单的代码,也应该用一个到父集合(Customer)的引用.因为我们的订单对象必须有个唯一的OrderID,我将设置该ID为一个负自增值.我们的"Orders"数据集DataSet包含一个OrderID列,该列设置为一个自增列;Order对象中的ID属性设置为一个负值,是为了避免在将一个新的Order行插入到数据库中时,发生冲突.在服务器端,当在Order表中插入一个新行时,数据库服务器将添加一个新的OrderID值,并且,一个新的唯一OrderID值将在更新的DataSet中返回,而且,应该与客户端的对象的值保持同步(我将在本文档的下个小结中解释该特性).
private void ordersBindingSource_AddingNew(object sender, AddingNewEventArgs e)
{
OrderBO order = new OrderBO();
order.IsNew = true;
order.IsDirty = true;
order.OrderDate = DateTime.Today;
order.ProductName = "[新产品名]"; 
//--- Set Temporary OrderID - Will be set to negative
//value to avoid update conflicts
m_lastOrderID--;
order.OrderId = m_lastOrderID; 
//--- Get the Current Customer
CustomerBO currentCustomer = (CustomerBO) customerBOBindingSource.Current; 
if (!(currentCustomer == null))
{
order.Customer = currentCustomer;
}
else
{
throw new NullReferenceException("订单的客户找不到!");
}
e.NewObject = order;
order = null;
}处理改进的事件对于表现层的开发人员来说非常显然.这里没有什么专门处理CustomerBO或者OrderBO的属性修改部分的类.我们将逐步地讨论这些类.这些辅助类部署在解决方案的业务层集合中.
让我们以IEventPublisher接口开始介绍,该接口有一套对象属性修改事件的蓝图.让我们进一步考察这个接口类:
public interface IEventPublisher
{
void RegisterListener<T>(T p_listener) where T : IEventListener;
void UnregisterListener<T>(T p_listener) where T : IEventListener;
void NotifyListeners();
bool IsDirty { get; set;}
bool Initializing { get; set;}
bool IsNew { get; set;}
}该IEventPublisher接口有为监听对象注册和反注册所用的方法接口,当一个对象属性值改变时,通知监听者,还有2个属性设置,IsDirty属性用来将一个附加对象标识为修改的状态,另外,当加载对象数据时,Initializing属性设置为true(因此要预防加载对象中的数据过程中,启动该修改事件).
下一步,我们看看IEventListener接口.该接口含有一个到Publisher对象的引用(我们的概念中,指customer或者order对象),并且描述了一个方法的签名,该方法专门用来处理对象属性"修改"事件.
public interface IEventListener
{
void OnNotification(IEventPublisher p_publisher);
}Publisher类是每个自定义对象业务类的基础类.业务对象直接继承该Publisher类.该Publisher类含有"注册"和"反注册"监听对象的方法.监听对象就是指那些需要在业务对象类别的属性修改时,被通知的对象.一个典型的监听者是一个Windows Form.该基类也包含一些基础的属性,用来设置业务对象到一些初始状态,如"IsNew","IsDirty"(修改过的),"IsInitializing"状态.
public abstract class Publisher : IEventPublisher
{
private delegate void m_eventHandler(IEventPublisher p_publisher);
private event m_eventHandler m_event;
IEventPublisher 成员
}ObjectChangedListener类包含了OnNotification方法,当业务对象类(是注册到NotifyChanged事件中的)属性值发生改变时,执行该方法;
public class ObjectChangedListener : IEventListener
{
IEventListener 成员
}因此(看下面的代码),Notification事件被附加到set属性中.所以,当一个属性值变化时,该事件将抛出(CustomerBO的属性).
public string CustomerId
{
get { return m_CustomerId; }
set
{
m_CustomerId = value;
NotifyListeners();
}
} 
public string CompanyName
{
get { return m_CompanyName; }
set
{
m_CompanyName = value;
NotifyListeners();
}
} 当使用者单击保存按钮,下一步,代码将被执行,用新增的,修改的或者删除的对象,回写更新数据库.因为这里有很多相关的代码,我将在代码内部进行说明.
private void customerBOBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
//--- Validate the Value which loses control first
this.Validate();
//--- End the CurrentEdit on the BindingSources
customerBOBindingSource.EndEdit();
ordersBindingSource.EndEdit();
//--- Create Customer and Order List to hold the
//Changed objects
List<CustomerBO> changedCustomers = null;
List<OrderBO> changedOrders = null;
//--- Loop through the ObjectStacks to catch changed
//property data
foreach (Object obj in customerBOBindingSource)
{
CustomerBO customer = (CustomerBO) obj;
if (customer.IsDirty)
{
if (changedCustomers == null)
changedCustomers = new List<CustomerBO>();
changedCustomers.Add(customer);
}
foreach (OrderBO order in customer.Orders)
{
if (order.IsDirty)
{
if (changedOrders == null)
changedOrders = new List<OrderBO>();
changedOrders.Add(order);
}
}
customer = null;
}
if (changedCustomers != null || changedOrders != null || m_deletedCustomers != null || m_deletedOrders != null)
{
bool IsUpdateOK = true;
try
{
//--- Update through Business Object Layer
int numUpdate = m_customerBO.SaveCustomerOrders(changedCustomers,
m_deletedCustomers,
changedOrders,
m_deletedOrders);
//--- Display Success
MessageBox.Show(String.Format("{0}行成功更新到数据库!", numUpdate.ToString()));
}
catch (Exception ex)
{
IsUpdateOK = false;
//--- Show Error
MessageBox.Show(ex.Message, "发生错误,更新失败!");
}
finally
{
//--- Reset object state & Release Resources
if (IsUpdateOK)
{
//--- First Syncronize the OrderID's with
//Server Versions
if (changedOrders != null)
{
m_customerBO.SyncroOrderID(changedOrders);
}
if (changedCustomers != null)
{
foreach (CustomerBO customer in changedCustomers)
{
customer.IsDirty = false;
customer.IsNew = false;
}
changedCustomers = null;
}
if (changedOrders != null)
{
foreach (OrderBO order in changedOrders)
{
order.IsDirty = false;
order.IsNew = false;
}
changedOrders = null;
}
//--- Release Helper Objects
m_deletedCustomers = null;
m_deletedOrders = null;
//--- Refresh the OrderGrid
ordersDataGridView.Refresh();
}
}
}
}添加的和修改的对象可以在包含列表中被跟踪,删除的不能.因此,我们必须手动跟踪这些对象.所以,我们下一步必须在代码中部署下一个事件处理程序.
在定义部分:
public partial class CustomerAdmin : Form
{
private CustomerBO m_customerBO;
private List<CustomerBO> m_deletedCustomers = null;
private List<OrderBO> m_deletedOrders = null;
…
} 处理删除Customer或者Order对象的代码:
private void customerBODataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
if (m_deletedCustomers == null)
m_deletedCustomers = new List<CustomerBO>();
m_deletedCustomers.Add((CustomerBO)e.Row.DataBoundItem);
if (((CustomerBO)e.Row.DataBoundItem).Orders != null)
{
if (m_deletedOrders == null)
m_deletedOrders = new List<OrderBO>();
m_deletedOrders.AddRange(((CustomerBO) e.Row.DataBoundItem).Orders);
}
}
private void ordersDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
if (m_deletedOrders == null)
m_deletedOrders = new List<OrderBO>();
m_deletedOrders.Add((OrderBO)e.Row.DataBoundItem);
}最后,我们的BusinessLayer Class解决处理到DAL的更新.如下所示的实现方法,还用了Optimistic的途径处理了DbConcurrency问题.
public int SaveCustomerOrders(List<CustomerBO> p_addedOrModifiedCustomers,
List<CustomerBO> p_deletedCustomers,
List<OrderBO> p_addedOrModifiedOrders,
List<OrderBO> p_deletedOrders)
{
//--- Create the Service to update the Data
CustomerOrderService dataService = new CustomerOrderService();
Step 1 : Add Deleted Customer Object Information
Step 2 : Add Deleted Order Object Information
Step 3 : Add New/Modified Customer Object Information
Step 4 : Add New/Modified Order Object Information
Update through the DataService class
return 0;
}瞧… 都讲完了! 希望你喜欢这篇文章.


浙公网安备 33010602011771号