如何减少基于DataSet框架的代码输入量(二)
上一节讲的是如何把单表映射成一个实体和一个数据表。
这里我们讲述如何实现一对多的多表关联,这种关联在开发中也是最常见的。
通常一对多的情况下,我们要求,主表的primarykey应该是 从表的primarykey之一。为了区分各个表之间的PrimaryKey,我们引入了SecondaryKey的概念。用主表PrimaryKey+从表SecondaryKey构建了一个从表的PrimaryKey.呵呵,这里说得有点拗口。所有的sql都是基于这个模式构建的。所以,我们以SendOutDataSet为例,我出售了两样东西,那么我数据库里面应该存放 卖给谁SendOut 卖了什么东西SendOutItem .主表SendOut《Primarykey="SendID"》,从表SendOutItem.<primarykey=SendID secondaryKey=ItemID>
这样我们就构建这样的一个DataSet包含了两个DataTable.这两个DataTable把我们设置的PrimaryKey SecondaryKey的属性写入Column 的ExtendsProperties中。我们只需要做这样的一个从这个DataSet获取这样信息并且构建相应的Insert/Update/Delete等等方法的DataAccess就可以实现不需要再写那些讨厌的Insert/Update/Delete语句了。啊,世界从此清净了许多。
然后,我们还发现了还有不足的地方,那就是很多时候我们要删除一整个的数据,比如我卖出去一个单子的东西很多很杂,如果我用DataSet的形式的话,那么我就变成要一条一条的删除,所以,我们就制造了UpdateObject DeleteObject来减轻这种负担,比如我想删除某个人的订单<~_~!当然只是假设>,那么我需要构建两个Delete对象,然后传递给DataAccess,来执行两次的Sql,这样我们依然只是需要代码生成器来生成,还是不需要手写Update/Delete语句,目的也很明显,为了防止新手误用了错误的Sql语句,结果导致数据被删除。虽然可以通过日志的方式恢复,但是也很麻烦。
当然了,DataAccess还应该作更多的事情,比如获取服务器时间,表之间的拷贝<表结构一致的情况下>,依据PrimaryKey删除数据,根据PrimaryKey获取<SendID传入,根据DataSet来获取SendOut SendOutItem的数据。>。这些事情都是一劳永逸的,一旦做好,就可以反复的重新利用,而且整个框架也就两三个DataAccess。但是有很多的DataSet BusinessRule BusinessFacade。
sample code:
using System;
using FishSky.Data.Base;

namespace FishSkyTest.DataTest
{
///<summary>
/// SendOutEntity实体类
///</summary>
public class SendOutEntity : BaseEntity
{
构造函数

出库单

发票号

总计

操作员

操作员中文名

客户代码

客户中文名

备注

货款付讫

出售日期
}
}
using System;
using FishSky.Data.Base;

namespace FishSkyTest.DataTest
{
///<summary>
/// SendOutItemEntity实体类
///</summary>
public class SendOutItemEntity : BaseEntity
{
构造函数

送货单号

项目编号

库存编号

货物代码

货物中文名

数量

价格

进价

备注
}
}
using System;
using System.Data;
using FishSky.Data.Base;

namespace FishSkyTest.DataTest
{
public class SendOutDataTable : BaseDataTable
{
表格常量

构造函数

创建实体

获取指定行号的实体

设置实体值到DataTable
}
}
using System;
using System.Data;
using FishSky.Data.Base;

namespace FishSkyTest.DataTest
{
public class SendOutItemDataTable : BaseDataTable
{
表格常量

构造函数

创建实体

获取指定行号的实体

设置实体值到DataTable
}
}
using System;
using System.Runtime.Serialization;
using FishSky.Data.Base;

namespace FishSkyTest.DataTest
{
[Serializable]
public class SendOutDataSet : BaseDataSet
{
表格常量及数据表

构造函数

序列化的构造函数

建立数据集的表格
}
}
using System;
using System.Data;
using NUnit.Framework;
namespace FishSkyTest.DataTest
{
/// <summary>
/// SendOutDataSetTest 的摘要说明。----Multi-Table && Multi-Entity
/// </summary>
[TestFixture]
public class SendOutDataSetTest
{
private SendOutDataSet ds=new SendOutDataSet();

public SendOutDataSetTest()
{
}

[SetUp]
public void SetUp()
{
ds.SendOutTable.Rows.Clear();
ds.SendOutItemTable.Rows.Clear();
DataRow dr=ds.SendOutTable.NewRow();
dr[SendOutDataTable.Amount_SendOut]=300;
dr[SendOutDataTable.ChineseName_SendOut]="拉拉";
dr[SendOutDataTable.CustomerCode_SendOut]="aa";
dr[SendOutDataTable.CustomerName_SendOut]="asdfasdfasdf";
dr[SendOutDataTable.InvoiceNo_SendOut]="fapiaohao";
dr[SendOutDataTable.IsPaid_SendOut]=0;
dr[SendOutDataTable.Remark_SendOut]="remark";
dr[SendOutDataTable.SendOutDate_SendOut]=DateTime.Now;
dr[SendOutDataTable.SendOutNo_SendOut]="S001";
dr[SendOutDataTable.UserName_SendOut]="kevin";
ds.SendOutTable.Rows.Add(dr);

dr=ds.SendOutItemTable.NewRow();
dr[SendOutItemDataTable.ChineseName_SendOutItem]="lala vine";
dr[SendOutItemDataTable.InPrice_SendOutItem]=120;
dr[SendOutItemDataTable.ItemNo_SendOutItem]=1;
dr[SendOutItemDataTable.MerchandiseCode_SendOutItem]="lala";
dr[SendOutItemDataTable.Price_SendOutItem]=300;
dr[SendOutItemDataTable.Quantity_SendOutItem]=20;
dr[SendOutItemDataTable.Remark_SendOutItem]="remark";
dr[SendOutItemDataTable.SendOutNo_SendOutItem]="S001";
dr[SendOutItemDataTable.StockID_SendOutItem]="ST000001";
ds.SendOutItemTable.Rows.Add(dr);

}

[Test]
public void TestMultiNewEntity()
{
SetUp();
SendOutEntity outEntity=ds.SendOutTable.CreateEntity() as SendOutEntity;
outEntity.Amount=200;
outEntity.ChineseName="baasd";
outEntity.CustomerCode ="adfad";
outEntity.CustomerName ="seadifln";
outEntity.InvoiceNo ="Id932lnd";
outEntity.IsPaid ="N";
outEntity.Remark ="remarks";
outEntity.SendOutDate =DateTime.Now;
outEntity.SendOutNo ="S0002";
outEntity.UserName ="kevin";
ds.SendOutTable.SetEntity(outEntity);

SendOutItemEntity itemEntity =ds.SendOutItemTable.CreateEntity() as SendOutItemEntity;
itemEntity.ChineseName ="lala vines";
itemEntity.InPrice =120;
itemEntity.ItemNo=1;
itemEntity.MerchandiseCode ="lalades";
itemEntity.Price =200;
itemEntity.Quantity =200;
itemEntity.Remark ="adfad";
itemEntity.SendOutNo =outEntity.SendOutNo ;
itemEntity.StockID ="StkOutID";
ds.SendOutItemTable.SetEntity(itemEntity);

itemEntity =ds.SendOutItemTable.CreateEntity() as SendOutItemEntity;
itemEntity.ChineseName ="lala vines";
itemEntity.InPrice =120;
itemEntity.ItemNo=2;
itemEntity.MerchandiseCode ="galdiena";
itemEntity.Price =300;
itemEntity.Quantity =100;
itemEntity.Remark ="adfad";
itemEntity.SendOutNo =outEntity.SendOutNo ;
itemEntity.StockID ="StkOutID";
ds.SendOutItemTable.SetEntity(itemEntity);

Assert.AreEqual(ds.SendOutTable.Rows.Count,2) ;
Assert.AreEqual(ds.SendOutItemTable.Rows.Count,3) ;
Assert.IsFalse(ds.SendOutItemTable.SetEntity(outEntity));

}


}
}
这里我们讲述如何实现一对多的多表关联,这种关联在开发中也是最常见的。
通常一对多的情况下,我们要求,主表的primarykey应该是 从表的primarykey之一。为了区分各个表之间的PrimaryKey,我们引入了SecondaryKey的概念。用主表PrimaryKey+从表SecondaryKey构建了一个从表的PrimaryKey.呵呵,这里说得有点拗口。所有的sql都是基于这个模式构建的。所以,我们以SendOutDataSet为例,我出售了两样东西,那么我数据库里面应该存放 卖给谁SendOut 卖了什么东西SendOutItem .主表SendOut《Primarykey="SendID"》,从表SendOutItem.<primarykey=SendID secondaryKey=ItemID>
这样我们就构建这样的一个DataSet包含了两个DataTable.这两个DataTable把我们设置的PrimaryKey SecondaryKey的属性写入Column 的ExtendsProperties中。我们只需要做这样的一个从这个DataSet获取这样信息并且构建相应的Insert/Update/Delete等等方法的DataAccess就可以实现不需要再写那些讨厌的Insert/Update/Delete语句了。啊,世界从此清净了许多。
然后,我们还发现了还有不足的地方,那就是很多时候我们要删除一整个的数据,比如我卖出去一个单子的东西很多很杂,如果我用DataSet的形式的话,那么我就变成要一条一条的删除,所以,我们就制造了UpdateObject DeleteObject来减轻这种负担,比如我想删除某个人的订单<~_~!当然只是假设>,那么我需要构建两个Delete对象,然后传递给DataAccess,来执行两次的Sql,这样我们依然只是需要代码生成器来生成,还是不需要手写Update/Delete语句,目的也很明显,为了防止新手误用了错误的Sql语句,结果导致数据被删除。虽然可以通过日志的方式恢复,但是也很麻烦。
当然了,DataAccess还应该作更多的事情,比如获取服务器时间,表之间的拷贝<表结构一致的情况下>,依据PrimaryKey删除数据,根据PrimaryKey获取<SendID传入,根据DataSet来获取SendOut SendOutItem的数据。>。这些事情都是一劳永逸的,一旦做好,就可以反复的重新利用,而且整个框架也就两三个DataAccess。但是有很多的DataSet BusinessRule BusinessFacade。
sample code:
using System;
using FishSky.Data.Base;
namespace FishSkyTest.DataTest
{
///<summary>
/// SendOutEntity实体类
///</summary>
public class SendOutEntity : BaseEntity
{
构造函数
出库单 
发票号 
总计 
操作员 
操作员中文名 
客户代码 
客户中文名 
备注 
货款付讫 
出售日期
}
}
using System;
using FishSky.Data.Base;
namespace FishSkyTest.DataTest
{
///<summary>
/// SendOutItemEntity实体类
///</summary>
public class SendOutItemEntity : BaseEntity
{
构造函数
送货单号 
项目编号 
库存编号 
货物代码 
货物中文名 
数量 
价格 
进价 
备注
}
}
using System;
using System.Data;
using FishSky.Data.Base;
namespace FishSkyTest.DataTest
{
public class SendOutDataTable : BaseDataTable
{
表格常量 
构造函数
创建实体
获取指定行号的实体
设置实体值到DataTable
}
}
using System;
using System.Data;
using FishSky.Data.Base;
namespace FishSkyTest.DataTest
{
public class SendOutItemDataTable : BaseDataTable
{
表格常量 
构造函数
创建实体
获取指定行号的实体
设置实体值到DataTable
}
}
using System;
using System.Runtime.Serialization;
using FishSky.Data.Base;
namespace FishSkyTest.DataTest
{
[Serializable]
public class SendOutDataSet : BaseDataSet
{
表格常量及数据表
构造函数
序列化的构造函数
建立数据集的表格
}
}
using System;
using System.Data;
using NUnit.Framework;
namespace FishSkyTest.DataTest
{
/// <summary>
/// SendOutDataSetTest 的摘要说明。----Multi-Table && Multi-Entity
/// </summary>
[TestFixture]
public class SendOutDataSetTest
{
private SendOutDataSet ds=new SendOutDataSet();
public SendOutDataSetTest()
{
}
[SetUp]
public void SetUp()
{
ds.SendOutTable.Rows.Clear();
ds.SendOutItemTable.Rows.Clear();
DataRow dr=ds.SendOutTable.NewRow();
dr[SendOutDataTable.Amount_SendOut]=300;
dr[SendOutDataTable.ChineseName_SendOut]="拉拉";
dr[SendOutDataTable.CustomerCode_SendOut]="aa";
dr[SendOutDataTable.CustomerName_SendOut]="asdfasdfasdf";
dr[SendOutDataTable.InvoiceNo_SendOut]="fapiaohao";
dr[SendOutDataTable.IsPaid_SendOut]=0;
dr[SendOutDataTable.Remark_SendOut]="remark";
dr[SendOutDataTable.SendOutDate_SendOut]=DateTime.Now;
dr[SendOutDataTable.SendOutNo_SendOut]="S001";
dr[SendOutDataTable.UserName_SendOut]="kevin";
ds.SendOutTable.Rows.Add(dr);
dr=ds.SendOutItemTable.NewRow();
dr[SendOutItemDataTable.ChineseName_SendOutItem]="lala vine";
dr[SendOutItemDataTable.InPrice_SendOutItem]=120;
dr[SendOutItemDataTable.ItemNo_SendOutItem]=1;
dr[SendOutItemDataTable.MerchandiseCode_SendOutItem]="lala";
dr[SendOutItemDataTable.Price_SendOutItem]=300;
dr[SendOutItemDataTable.Quantity_SendOutItem]=20;
dr[SendOutItemDataTable.Remark_SendOutItem]="remark";
dr[SendOutItemDataTable.SendOutNo_SendOutItem]="S001";
dr[SendOutItemDataTable.StockID_SendOutItem]="ST000001";
ds.SendOutItemTable.Rows.Add(dr);
}
[Test]
public void TestMultiNewEntity()
{
SetUp();
SendOutEntity outEntity=ds.SendOutTable.CreateEntity() as SendOutEntity;
outEntity.Amount=200;
outEntity.ChineseName="baasd";
outEntity.CustomerCode ="adfad";
outEntity.CustomerName ="seadifln";
outEntity.InvoiceNo ="Id932lnd";
outEntity.IsPaid ="N";
outEntity.Remark ="remarks";
outEntity.SendOutDate =DateTime.Now;
outEntity.SendOutNo ="S0002";
outEntity.UserName ="kevin";
ds.SendOutTable.SetEntity(outEntity);
SendOutItemEntity itemEntity =ds.SendOutItemTable.CreateEntity() as SendOutItemEntity;
itemEntity.ChineseName ="lala vines";
itemEntity.InPrice =120;
itemEntity.ItemNo=1;
itemEntity.MerchandiseCode ="lalades";
itemEntity.Price =200;
itemEntity.Quantity =200;
itemEntity.Remark ="adfad";
itemEntity.SendOutNo =outEntity.SendOutNo ;
itemEntity.StockID ="StkOutID";
ds.SendOutItemTable.SetEntity(itemEntity);
itemEntity =ds.SendOutItemTable.CreateEntity() as SendOutItemEntity;
itemEntity.ChineseName ="lala vines";
itemEntity.InPrice =120;
itemEntity.ItemNo=2;
itemEntity.MerchandiseCode ="galdiena";
itemEntity.Price =300;
itemEntity.Quantity =100;
itemEntity.Remark ="adfad";
itemEntity.SendOutNo =outEntity.SendOutNo ;
itemEntity.StockID ="StkOutID";
ds.SendOutItemTable.SetEntity(itemEntity);
Assert.AreEqual(ds.SendOutTable.Rows.Count,2) ;
Assert.AreEqual(ds.SendOutItemTable.Rows.Count,3) ;
Assert.IsFalse(ds.SendOutItemTable.SetEntity(outEntity));
}

}
}



浙公网安备 33010602011771号