三层架构已经被说了很多次,今天来谈谈我的看法。
.net下典型的三层架构就是UI,业务逻辑层和数据访问层。
UI层暂且不表,就谈谈争论最大的业务逻辑层和数据访问层吧,这是争论最多,也是被误解的最多的一点。
拿petshop4为例,什么都先别说,一看代码就闻到了bad smell,为什么,看看那个IDal,SqlServerDAL,还有OracleDA),到处都是重复的代码,下面几个随便找的方法:
public IList<ProductInfo> GetProductsBySearch(string[] keywords) {
IList<ProductInfo>
productsBySearch = new List<ProductInfo>();
//Create a new query string
int numKeywords = keywords.Length;
StringBuilder sql = new
StringBuilder(SQL_SELECT_PRODUCTS_BY_SEARCH1);
//Add each keyword to the query
for (int i = 0; i
< numKeywords; i++) {
sql.Append(string.Format(SQL_SELECT_PRODUCTS_BY_SEARCH2,
PARM_KEYWORD + i));
sql.Append(i + 1 < numKeywords ? SQL_SELECT_PRODUCTS_BY_SEARCH3 :
SQL_SELECT_PRODUCTS_BY_SEARCH4);
}
//See if we have a set of cached parameters based on a
similar qquery
string sqlProductsBySearch = sql.ToString();
OracleParameter[] parms = OracleHelper.GetCachedParameters(sqlProductsBySearch);
// If the parameters are null build a new set
if (parms == null) {
parms =
new OracleParameter[numKeywords];
for (int i = 0; i
< numKeywords; i++)
parms[i] = new OracleParameter(PARM_KEYWORD
+ i, OracleType.VarChar, 80);
// Cache the new parameters
OracleHelper.CacheParameters(sqlProductsBySearch,
parms);
}
// Bind the new
parameters
for (int i = 0; i
< numKeywords; i++)
parms[i].Value = keywords[i];
//Finally execute the query
using (OracleDataReader
rdr = OracleHelper.ExecuteReader(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sqlProductsBySearch, parms)) {
while (rdr.Read()) {
ProductInfo product = new
ProductInfo(rdr.GetString(0), rdr.GetString(1),
rdr.GetString(2), rdr.GetString(3), rdr.GetString(4));
productsBySearch.Add(product);
}
}
return productsBySearch;
}
public void Insert(OrderInfo order) {
int orderId = 0;
// Get the parameters
OracleParameter[]
completeOrderParms = null;
OracleParameter[] orderParms = GetOrderParameters();
OracleParameter statusParm = new
OracleParameter(PARM_ORDER_ID, OracleType.Number);
// Bind the parameters
orderParms[1].Value = order.UserId;
orderParms[2].Value = order.Date;
orderParms[3].Value = order.ShippingAddress.Address1;
orderParms[4].Value = order.ShippingAddress.Address2;
orderParms[5].Value = order.ShippingAddress.City;
orderParms[6].Value = order.ShippingAddress.State;
orderParms[7].Value = order.ShippingAddress.Zip;
orderParms[8].Value = order.ShippingAddress.Country;
orderParms[9].Value = order.BillingAddress.Address1;
orderParms[10].Value = order.BillingAddress.Address2;
orderParms[11].Value = order.BillingAddress.City;
orderParms[12].Value = order.BillingAddress.State;
orderParms[13].Value = order.BillingAddress.Zip;
orderParms[14].Value = order.BillingAddress.Country;
orderParms[15].Value = order.OrderTotal;
orderParms[16].Value = order.BillingAddress.FirstName;
orderParms[17].Value = order.BillingAddress.LastName;
orderParms[18].Value = order.ShippingAddress.FirstName;
orderParms[19].Value = order.ShippingAddress.LastName;
orderParms[20].Value
= order.AuthorizationNumber.Value;
// Create the connection to the database
using (OracleConnection
conn = new OracleConnection(OracleHelper.ConnectionStringOrderDistributedTransaction))
{
// Open the database connection
conn.Open();
// Get the order id for the order sequence
orderId
= Convert.ToInt32(OracleHelper.ExecuteScalar(conn,
CommandType.Text, SQL_GET_ORDERNUM));
orderParms[0].Value = orderId;
statusParm.Value = orderId;
// Total number of parameters = order parameters count + 1
+ (5 * number of lines)
int numberOfParameters = orderParms.Length + 1 + (5 *
order.LineItems.Length);
//Create a set of parameters
completeOrderParms = new OracleParameter[numberOfParameters];
//Copy the parameters to the execution parameters
orderParms.CopyTo(completeOrderParms, 0);
completeOrderParms[orderParms.Length]
= statusParm;
//Create a batch statement
StringBuilder finalSQLQuery = new StringBuilder("BEGIN ");
// Append the order header statements
finalSQLQuery.Append(SQL_INSERT_ORDER);
finalSQLQuery.Append("; ");
finalSQLQuery.Append(SQL_INSERT_STATUS);
finalSQLQuery.Append("; ");
int index = orderParms.Length + 1;
int i = 1;
// Append each line item to the batch statement
foreach (LineItemInfo
item in order.LineItems) {
//Add
the appropriate parameters
completeOrderParms[index] = new OracleParameter(PARM_ORDER_ID + i, OracleType.Number);
completeOrderParms[index++].Value = orderId;
completeOrderParms[index] = new OracleParameter(PARM_LINE_NUMBER + i, OracleType.Number);
completeOrderParms[index++].Value = item.Line;
completeOrderParms[index] = new OracleParameter(PARM_ITEM_ID + i, OracleType.Char, 10);
completeOrderParms[index++].Value
= item.ItemId;
completeOrderParms[index] = new OracleParameter(PARM_QUANTITY + i, OracleType.Number);
completeOrderParms[index++].Value = item.Quantity;
comple