下面就是项目的架构,ADO为数据访问层代码(即对某表的增,删,改,查),Model为模型层代码(对表的映射).Model下的TProduct.cs为代码生成器生成的原始模型层,当然它和数据表是一一对应的.而TProduct_Sub.cs为扩展后的模型类, 对应ADO目录也是一样道理.Sub结尾即为对原先的扩展.这样就可以避免重新生成代码时不小心把对原有代码的修改覆盖掉.
(代码生成器http://win.51aspx.com/CV/ClassGenerateProper/生成的代码)生成的代码,
TProduct 表到类的映射.
using System;
using System.Data;
/// <summary>
/// 产品信息
/// </summary>
[Serializable]
public class TProduct
{
private int pid;
public int Pid
{
get{ return pid; }
set{ pid = value; }
}
/// <summary>
/// 产品名称
/// </summary>
private string pName;
/// <summary>
/// 产品名称
/// </summary>
public string PName
{
get{ return pName; }
set{ pName = value; }
}
/// <summary>
/// 价格
/// </summary>
private double price;
/// <summary>
/// 价格
/// </summary>
public double Price
{
get{ return price; }
set{ price = value; }
}
/// <summary>
/// 分类ID(tClass.classID)
/// </summary>
private int classid;
/// <summary>
/// 分类ID(tClass.classID)
/// </summary>
public int Classid
{
get{ return classid; }
set{ classid = value; }
}
/// <summary>
/// 图片名称
/// </summary>
private string photo;
/// <summary>
/// 图片名称
/// </summary>
public string Photo
{
get{ return photo; }
set{ photo = value; }
}
/// <summary>
/// 产品信息描述
/// </summary>
private string description;
/// <summary>
/// 产品信息描述
/// </summary>
public string Description
{
get{ return description; }
set{ description = value; }
}
/// <summary>
/// 卖家ID
/// </summary>
private Int64 seller;
/// <summary>
/// 卖家ID
/// </summary>
public Int64 Seller
{
get{ return seller; }
set{ seller = value; }
}
}
TProduct表的对应的ADO(数据访问操作,这里面用到了通用数据库组件http://win.51aspx.com/CV/CommonTest/ 或 http://singleyw.download.csdn.net/
)代码
using System;
using System.Data;
using Common.DataAccess;
using System.Collections.Generic;
/// <summary>
/// 产品信息
/// </summary>
[Serializable]
public class ADOTProduct
{
IDBOperator idb = DBOperator.GetInstance();
/// <summary>
/// 添加产品信息 TProduct对象(即:一条记录)
/// </summary>
public int Add(TProduct tProduct)
{
string sql = "INSERT INTO tProduct (pName,price,classid,photo,description,seller) VALUES (@pName,@price,@classid,@photo,@description,@seller)";
if (string.IsNullOrEmpty(tProduct.PName))
{
idb.AddParameter("@pName", "''");
}
else
{
idb.AddParameter("@pName", tProduct.PName);
}
if (tProduct.Price == 0)
{
idb.AddParameter("@price", 0);<br /> }
else
{
idb.AddParameter("@price", tProduct.Price);
}
if (tProduct.Classid == 0)
{
idb.AddParameter("@classid", 0);
}
else
{
idb.AddParameter("@classid", tProduct.Classid);
}
if (string.IsNullOrEmpty(tProduct.Photo))
{
idb.AddParameter("@photo", DBNull.Value);
}
else
{
idb.AddParameter("@photo", tProduct.Photo);
}
if (string.IsNullOrEmpty(tProduct.Description))
{
idb.AddParameter("@description", DBNull.Value);
}
else
{
idb.AddParameter("@description", tProduct.Description);
}
if (tProduct.Seller == 0)
{
idb.AddParameter("@seller", 0);
}
else
{
idb.AddParameter("@seller", tProduct.Seller);
}
return idb.ExeCmd(sql);
}
/// <summary>
/// 更新产品信息 TProduct对象(即:一条记录
/// </summary>
public int Update(TProduct tProduct)
{
string sql = @"UPDATE tProduct SET
pName=@pName,price=@price,classid=@classid,photo=@photo,description=@description,seller=@seller WHERE 1=1
and pid=@pid";
if (string.IsNullOrEmpty(tProduct.PName))
{
idb.AddParameter("@pName", "''");
}
else
{
idb.AddParameter("@pName", tProduct.PName);
}
if (tProduct.Price == 0)
{
idb.AddParameter("@price", 0);
}
else
{
idb.AddParameter("@price", tProduct.Price);
}
if (tProduct.Classid == 0)
{
idb.AddParameter("@classid", 0);
}
else
{
idb.AddParameter("@classid", tProduct.Classid);
}
if (string.IsNullOrEmpty(tProduct.Photo))
{
idb.AddParameter("@photo", DBNull.Value);
}
else
{
idb.AddParameter("@photo", tProduct.Photo);
}
if (string.IsNullOrEmpty(tProduct.Description))
{
idb.AddParameter("@description", DBNull.Value);
}
else
{
idb.AddParameter("@description", tProduct.Description);
}
if (tProduct.Seller == 0)
{
idb.AddParameter("@seller", 0);
}
else
{
idb.AddParameter("@seller", tProduct.Seller);
}
idb.AddParameter("@pid", tProduct.Pid);
return idb.ExeCmd(sql);
}
/// <summary>
/// 删除产品信息 TProduct对象(即:一条记录
/// </summary>
public int Delete(int pid)
{
string sql = "DELETE tProduct WHERE 1=1 AND pid=@pid ";
idb.AddParameter("@pid", pid);
return idb.ExeCmd(sql);
}
/// <summary>
/// 获取指定的产品信息 TProduct对象(即:一条记录
/// </summary>
public TProduct GetByKey(int pid)
{
TProduct tProduct = new TProduct();
string sql = "SELECT pid,pName,price,classid,photo,description,seller FROM tProduct WHERE 1=1 AND pid=@pid ";
idb.AddParameter("@pid", pid);
DataTable dt = idb.ReturnDataTable(sql);
foreach (DataRow dr in dt.Rows)
{
if (dr["pid"] != DBNull.Value) tProduct.Pid = Convert.ToInt32(dr["pid"]);
if (dr["pName"] != DBNull.Value) tProduct.PName = Convert.ToString(dr["pName"]);
if (dr["price"] != DBNull.Value) tProduct.Price = Convert.ToDouble(dr["price"]);
if (dr["classid"] != DBNull.Value) tProduct.Classid = Convert.ToInt32(dr["classid"]);
if (dr["photo"] != DBNull.Value) tProduct.Photo = Convert.ToString(dr["photo"]);
if (dr["description"] != DBNull.Value) tProduct.Description = Convert.ToString(dr["description"]);
if (dr["seller"] != DBNull.Value) tProduct.Seller = Convert.ToInt64(dr["seller"]);
}
return tProduct;
}
/// <summary>
/// 获取指定的产品信息 TProduct对象集合
/// </summary>
public List<TProduct> GetListByWhere(string strCondition)
{
List<TProduct> ret = new List<TProduct>();
string sql = "SELECT pid,pName,price,classid,photo,description,seller FROM tProduct WHERE 1=1 ";
if(!string.IsNullOrEmpty(strCondition))
{
strCondition.Replace('\'','"'); //防sql注入
sql += strCondition ;
}
DataTable dt = idb.ReturnDataTable(sql);
foreach (DataRow dr in dt.Rows)
{
TProduct tProduct = new TProduct();
if (dr["pid"] != DBNull.Value) tProduct.Pid = Convert.ToInt32(dr["pid"]);
if (dr["pName"] != DBNull.Value) tProduct.PName = Convert.ToString(dr["pName"]);
if (dr["price"] != DBNull.Value) tProduct.Price = Convert.ToDouble(dr["price"]);
if (dr["classid"] != DBNull.Value) tProduct.Classid = Convert.ToInt32(dr["classid"]);
if (dr["photo"] != DBNull.Value) tProduct.Photo = Convert.ToString(dr["photo"]);
if (dr["description"] != DBNull.Value) tProduct.Description = Convert.ToString(dr["description"]);
if (dr["seller"] != DBNull.Value) tProduct.Seller = Convert.ToInt64(dr["seller"]);
ret.Add(tProduct);
}
return ret;
}
/// <summary>
/// 获取所有的产品信息 TProduct对象(即:一条记录
/// </summary>
public List<TProduct> GetAll()
{
List<TProduct> ret = new List<TProduct>();
string sql = "SELECT pid,pName,price,classid,photo,description,seller FROM tProduct ";
DataTable dt = idb.ReturnDataTable(sql);
foreach (DataRow dr in dt.Rows)
{
TProduct tProduct = new TProduct();
if (dr["pid"] != DBNull.Value) tProduct.Pid = Convert.ToInt32(dr["pid"]);
if (dr["pName"] != DBNull.Value) tProduct.PName = Convert.ToString(dr["pName"]);
if (dr["price"] != DBNull.Value) tProduct.Price = Convert.ToDouble(dr["price"]);
if (dr["classid"] != DBNull.Value) tProduct.Classid = Convert.ToInt32(dr["classid"]);
if (dr["photo"] != DBNull.Value) tProduct.Photo = Convert.ToString(dr["photo"]);
if (dr["description"] != DBNull.Value) tProduct.Description = Convert.ToString(dr["description"]);
if (dr["seller"] != DBNull.Value) tProduct.Seller = Convert.ToInt64(dr["seller"]);
ret.Add(tProduct);
}
return ret;
}
}
上面的代码可能已经不错了,但是实际开发中, 我们可能需要的结果不只那些信息,比如我们还需要商家信息,还需要地区信息,这样的需求就必需联接查询出相关信息
如:
SELECT a.pid,pName,price,d.classid,d.className,d.orderid,d.[description] as ddescription,a.photo,a.[description],a.seller,b.uName,b.tel,b.areaid,c.parentid,c.areaName,c.enable
FROM tProduct a
left join tuser b on a.seller=b.uid
left join tarea c on b.areaid=c.areaid
left join tClass d on a.classid=d.classID
结果如下:
这样的结果如果用List<TProduct> 对象来存储当然是没办法存储了,所以我们需要对TProduct进行扩展--继承,对,我用TProduct_Sub : TProduct这样来实现,好处就是我们不需要重复定义TProduct里的信息,由此,我觉得,用继承来对原有数据进行扩展就应该是合理的了
using System;
using System.Data;
/// <summary>
/// 产品信息
/// </summary>
[Serializable]
public class TProduct_Sub : TProduct
{
TArea tarea;
/// <summary>
/// 地区信息
/// </summary>
public TArea AreaInfo
{
get
{
return tarea;
}
set { tarea = value; }
}
TClass tclass;
/// <summary>
/// 商品类型
/// </summary>
public TClass ClassInfo
{
get { return tclass; }
set { tclass = value; }
}
TUser seller;
/// <summary>
/// 用户信息
/// </summary>
public TUser SellerInfo
{
get { return seller; }
set { seller = value; }
}
}
注意,上面代码中用TArea AreaInfo,TClass ClassInfo,TUser SellerInfo它们在原来的基础上组合得到了很好的代码重用.
当然还需要数据访问时的对应的扩展思路差不多ADOTProduct_Sub : ADOTProduct
using System;
using System.Data;
using Common.DataAccess;
using System.Collections.Generic;
/// <summary>
/// 产品信息
/// </summary>
[Serializable]
public class ADOTProduct_Sub:ADOTProduct
{
IDBOperator idb = DBOperator.GetInstance();
/// <summary>
/// 获取某产品扩展信息
/// </summary>
/// <param name="pid">产品ID</param>
/// <returns></returns>
public TProduct_Sub GetSubByKey(int pid)
{
TProduct_Sub tProduct = null;
List<TProduct_Sub> sub = GetSubListByWhere(" and a.pid =" + pid.ToString());
if (sub.Count>0)
{
tProduct = sub[0];
}
return tProduct;
}
/// <summary>
/// 获取指定的产品信息 TProduct_Sub对象集合
/// </summary>
public List<TProduct_Sub> GetSubListByWhere(string strCondition)
{
List<TProduct_Sub> ret = new List<TProduct_Sub>();
#region sql
string sql = @"
SELECT a.pid,pName,price
,d.classid,d.className,d.orderid,d.[description] as ddescription
,a.photo,a.[description],a.seller
,b.uName,b.tel,b.areaid
,c.parentid,c.areaName,c.enable
FROM tProduct a
left join tuser b on a.seller=b.uid
left join tarea c on b.areaid=c.areaid
left join tClass d on a.classid=d.classID
WHERE 1=1 ";
#endregion
if (!string.IsNullOrEmpty(strCondition))
{
strCondition.Replace('\'', '"'); //防sql注入
sql += strCondition;
}
DataTable dt = idb.ReturnDataTable(sql);
foreach (DataRow dr in dt.Rows)
{
TProduct_Sub tProduct = new TProduct_Sub();
if (dr["pid"] != DBNull.Value) tProduct.Pid = Convert.ToInt32(dr["pid"]);
if (dr["pName"] != DBNull.Value) tProduct.PName = Convert.ToString(dr["pName"]);
if (dr["price"] != DBNull.Value) tProduct.Price = Convert.ToDouble(dr["price"]);
if (dr["classid"] != DBNull.Value)
{
tProduct.Classid = Convert.ToInt32(dr["classid"]);
tProduct.ClassInfo = new TClass();
tProduct.ClassInfo.ClassID = Convert.ToInt32(dr["classid"]);
tProduct.ClassInfo.ParentID = Convert.ToInt32(dr["ParentID"]);
tProduct.ClassInfo.OrderID = Convert.ToInt32(dr["OrderID"]);
tProduct.ClassInfo.ClassName = dr["ClassName"].ToString();
tProduct.ClassInfo.Description = dr["ddescription"].ToString();
}
if (dr["photo"] != DBNull.Value) tProduct.Photo = Convert.ToString(dr["photo"]);
if (dr["description"] != DBNull.Value) tProduct.Description = Convert.ToString(dr["description"]);
if (dr["seller"] != DBNull.Value)
{
tProduct.Seller = Convert.ToInt64(dr["seller"]);
tProduct.SellerInfo = new TUser();
tProduct.SellerInfo.Uid = Convert.ToInt64(dr["seller"]);
tProduct.SellerInfo.UName = dr["UName"].ToString();
tProduct.SellerInfo.Tel = dr["tel"].ToString();
}
if (dr["AreaID"] != DBNull.Value)
{
tProduct.AreaInfo = new TArea();
tProduct.AreaInfo.AreaID = Convert.ToInt32(dr["AreaID"]);
if (null != tProduct.SellerInfo)
{
tProduct.SellerInfo.AreaID = Convert.ToInt32(dr["AreaID"]);
}
tProduct.AreaInfo.AreaName = dr["AreaName"].ToString();
tProduct.AreaInfo.ParentID = Convert.ToInt32(dr["ParentID"]);
tProduct.AreaInfo.Enable = Convert.ToBoolean(dr["Enable"]);
}
ret.Add(tProduct);
}
return ret;
}
/// <summary>
/// 获取所有的产品信息 TProduct对象(即:一条记录
/// </summary>
public List<TProduct_Sub> GetSubAll()
{
return GetSubListByWhere("");
}
}
如此我们就实现了扩展部分(存储扩展,数据访问扩展),那我们如何绑定到控件(Repeater,GridView..)?
<asp:Repeater ID="rptProduct" runat="server">
<ItemTemplate>
<li class="product">
<a href="ProductDetails.aspx?pid=<%# Eval("pid") %>">
<div id="img"><img width="100px" height="100px" alt="商品图片" src='<%# Eval("photo") %>'/></div>
<div id="title"><%# Eval("pname") %></div>
<div id="price"><%# Eval("price") %></div>
<div id="seller"><%# Eval("SellerInfo.UName")%></div>
<div id="city"><%# Eval("AreaInfo.AreaName")%></div>
</a>
</li>
<li class="clear"></li>
</ItemTemplate>
</asp:Repeater>
注意<%# Eval("SellerInfo.UName") %> 这样的绑定是不是很对象化?
不过有一点,这种方式不能做双向绑定如<%# Bind("SellerInfo.UName") %> ,这可是不行了哈
我没用过java,不过大概了解下,这应该就是hibernate架构的思想了,要有时间把这个架构实现下,不说不用写代码搞开发,起码可以节略80%的代码