這次實驗主要是開發基於.net framework的窗體應用程序。我感覺這次實驗讓我學到了挺多東西。我做的是一個加州招待所管理系統,就是瞎扯淡。。囧。。。
第一就是儘量減少模塊(不知道寫了個這麼水的實驗能不能稱得上是模塊,暫時先這麼叫着吧,顯得牛B一點)之間的耦合性,這個特別重要。之前總是聽一些什麼減少模塊之間的耦合的觀點,沒有意識到有什麼用,以爲是用來裝B的,但是這次讓我深深地意識到了這個advice的重要性。我對這個advice的理解就是各部分分工要非常明確,負責processing data的專門processing data,負責操作UI的專門來操作UI,諸如此類。這個在android的開發中也有所體現,即intent的機制。
此外感覺總是對數據庫的增刪改查沒啥意思,於是就想通過將sql語句設計的複雜一點來幫助分擔一些程序邏輯的複雜程度。
第一在這個實驗中完全是用來裝B的,就是數據庫的分頁查詢與分頁顯示,這個功能在一些實際的應用中比較有用,例如當數據量很大時,不可能一次都讀出來。
"select top " + NUMBER_IN_A_PAGE + " * from " + DBKEYS.ROOM_INFO_TABLE_NAME
+ " where RoomNumber not in (select top " + page * NUMBER_IN_A_PAGE + " RoomNumber from " + DBKEYS.ROOM_INFO_TABLE_NAME + ")";
其中NUMBER_IN_A_PAGE是每頁的數量,對應的C#代碼如下:
這個函數是查詢數據庫,返回一個DataSet供填充DataGridView使用:
/// <summary>
/// 根據給定的sql字符串查詢數據,返回結果DataSet,flag爲區分函數重載標誌
/// </summary>
/// <param name="sqlString"></param>
/// <param name="flag"></param>
/// <returns></returns>
public DataSet inquiry(String sqlString,Boolean flag)
{
SqlCommand command;
SqlDataAdapter adapter;
DataSet dataSet;
try
{
command = new SqlCommand(sqlString, connection);
adapter = new SqlDataAdapter(command);
dataSet = new DataSet();
adapter.Fill(dataSet);
return dataSet;
}
catch (SqlException e)
{
Console.WriteLine(e.Message + flag);
return null;
}
}
/// <summary>
/// 設置setDataGridView的顯示
/// </summary>
private Boolean setDataGridView(int page)
{
String sqlString = "select top " + NUMBER_IN_A_PAGE + " * from " + DBKEYS.ROOM_INFO_TABLE_NAME
+ " where RoomNumber not in (select top " + page * NUMBER_IN_A_PAGE + " RoomNumber from " + DBKEYS.ROOM_INFO_TABLE_NAME + ")";
DataSet dataSet = dao.inquiry(sqlString, true);
// 說明沒有查到結果,到達了頁首或者頁尾
if (dataSet == null || dataSet.Tables.Count == 0 || dataSet.Tables[0].Rows.Count <= 0)
{
return false;
}
DataTable tableFirst = dataSet.Tables[0]; // 用DataTable 取 DataSet中的第一個表
// 設置DataGridView的列名
foreach (DataColumn dc in tableFirst.Columns)
{
RoomInfoDataGridView.Columns.Add(dc.ColumnName, dc.ColumnName);
}
// 每次新建一行將數據填到DataGridView中
foreach (DataRow dr in tableFirst.Rows)
{
DataGridViewRow vr = new DataGridViewRow();
foreach (DataGridViewColumn dc in RoomInfoDataGridView.Columns)
{
vr.Cells.Add(dc.CellTemplate.Clone() as DataGridViewCell);
vr.Cells[vr.Cells.Count - 1].Value = dr[dc.Name];
}
RoomInfoDataGridView.Rows.Add(vr);
}
// 設置RoomInfoDataGridView禁止根據列排序
int i;
for (i = 0; i < this.RoomInfoDataGridView.Columns.Count; i++) { }
this.RoomInfoDataGridView.Columns[--i].SortMode = DataGridViewColumnSortMode.NotSortable;
return true;
}
還有一個sql語句是日期的比較,簡單說來就是給定個date,選出date在ExpectiveLiveDate和從ExpectiveLiveDate算起ExpextiveLastingTime天后之間的記錄。
"select * from VisitorBookInfo where ( '" + date + "'"
+" between ExpectiveLiveDate and dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate))";
對應的C#函數:
/// <summary>
/// 根據查詢日期填充表格
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
private Boolean setDataGridView(String date)
{
String sqlString = "select * from VisitorBookInfo where ( '" + date + "'"
+" between ExpectiveLiveDate and dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate))";
DataSet dataSet = dao.inquiry(sqlString, true);
// 說明沒有查到結果
if (dataSet == null || dataSet.Tables.Count == 0 || dataSet.Tables[0].Rows.Count <= 0)
{
return false;
}
DataTable tableFirst = dataSet.Tables[0]; // 用DataTable 取 DataSet中的第一個表
// 設置DataGridView的列名
foreach (DataColumn dc in tableFirst.Columns)
{
RoomInfoDataGridView.Columns.Add(dc.ColumnName, dc.ColumnName);
}
// 每次新建一行將數據填到DataGridView中
foreach (DataRow dr in tableFirst.Rows)
{
DataGridViewRow vr = new DataGridViewRow();
foreach (DataGridViewColumn dc in RoomInfoDataGridView.Columns)
{
vr.Cells.Add(dc.CellTemplate.Clone() as DataGridViewCell);
vr.Cells[vr.Cells.Count - 1].Value = dr[dc.Name];
}
RoomInfoDataGridView.Rows.Add(vr);
}
// 設置RoomInfoDataGridView禁止根據列排序
int i;
for (i = 0; i < this.RoomInfoDataGridView.Columns.Count; i++) { }
this.RoomInfoDataGridView.Columns[--i].SortMode = DataGridViewColumnSortMode.NotSortable;
return true;
}
這個sql語句是選出某一層的房間,就是比如我要選出7樓的房間,也就是選出所有房間號以7開頭的,比如702,711等:
"select * from RoomInfo where(ASCII(RoomNumber) = ASCII('" + level +"'))"
對應的C#函數:
/// <summary>
/// 根據樓層填充表格,flag爲重載函數標誌
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
private Boolean setDataGridView(String level,Boolean flag)
{
String sqlString = "select * from RoomInfo where(ASCII(RoomNumber) = ASCII('" + level +"'))";
DataSet dataSet = dao.inquiry(sqlString, true);
// 說明沒有查到結果
if (dataSet == null || dataSet.Tables.Count == 0 || dataSet.Tables[0].Rows.Count <= 0)
{
return false;
}
DataTable tableFirst = dataSet.Tables[0]; // 用DataTable 取 DataSet中的第一個表
// 設置DataGridView的列名
foreach (DataColumn dc in tableFirst.Columns)
{
RoomInfoDataGridView.Columns.Add(dc.ColumnName, dc.ColumnName);
}
// 每次新建一行將數據填到DataGridView中
foreach (DataRow dr in tableFirst.Rows)
{
DataGridViewRow vr = new DataGridViewRow();
foreach (DataGridViewColumn dc in RoomInfoDataGridView.Columns)
{
vr.Cells.Add(dc.CellTemplate.Clone() as DataGridViewCell);
vr.Cells[vr.Cells.Count - 1].Value = dr[dc.Name];
}
RoomInfoDataGridView.Rows.Add(vr);
}
// 設置RoomInfoDataGridView禁止根據列排序
int i;
for (i = 0; i < this.RoomInfoDataGridView.Columns.Count; i++) { }
this.RoomInfoDataGridView.Columns[--i].SortMode = DataGridViewColumnSortMode.NotSortable;
return true;
}
這個是比較牛B的一條語句了,同時查詢兩個表,實現的功能就是我想預定房間,給你一個預定的日期和我要預定的天數,你給我找出現在爲空的並且沒有在裝修的,而且那天沒有預定記錄的房間(貌似邏輯有點錯誤,我要預定那天的,你爲啥限制我現在必須也得爲空和現在不能在裝修?!其實刪掉那兩個等於0的查詢限制就好,不過不影響這條語句的牛B程度):
select * from RoomInfo where (RoomInfo.RoomNumber not in ((select VisitorBookInfo.RoomNumber from VisitorBookInfo where ('" + dateBegin + "' between ExpectiveLiveDate and dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate)) and (ExpectiveLiveDate between '" + dateBegin + "' and '" + dateEnd + "')or ('" + dateBegin + "'=ExpectiveLiveDate)or('" + dateEnd + "'=dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate)))))"
對應的C#函數:
/// <summary>
/// 根據開始日期和結束日期查詢在該日期內房間的預定情況
/// </summary>
/// <param name="dateBegin"></param>
/// <param name="dateEnd"></param>
/// <returns></returns>
private Boolean setDataGridView(String dateBegin,String dateEnd)
{
//String sqlString = "select * from RoomInfo where (RoomInfo.RoomNumber not in ((select VisitorBookInfo.RoomNumber from VisitorBookInfo where not ('" + dateBegin + "' not between ExpectiveLiveDate and dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate)) and (ExpectiveLiveDate not between '" + dateBegin + "' and '" + dateEnd + "'))))";
String sqlString = "select * from RoomInfo where (RoomInfo.RoomNumber not in ((select VisitorBookInfo.RoomNumber from VisitorBookInfo where ('" + dateBegin + "' between ExpectiveLiveDate and dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate)) and (ExpectiveLiveDate between '" + dateBegin + "' and '" + dateEnd + "')or ('" + dateBegin + "'=ExpectiveLiveDate)or('" + dateEnd + "'=dateadd(day,ExpextiveLastingTime,ExpectiveLiveDate)))))";
DataSet dataSet = dao.inquiry(sqlString, true);
// 說明沒有查到結果
if (dataSet == null || dataSet.Tables.Count == 0 || dataSet.Tables[0].Rows.Count <= 0)
{
return false;
}
DataTable tableFirst = dataSet.Tables[0]; // 用DataTable 取 DataSet中的第一個表
// 設置DataGridView的列名
foreach (DataColumn dc in tableFirst.Columns)
{
RoomInfoDataGridView.Columns.Add(dc.ColumnName, dc.ColumnName);
}
// 每次新建一行將數據填到DataGridView中
foreach (DataRow dr in tableFirst.Rows)
{
DataGridViewRow vr = new DataGridViewRow();
foreach (DataGridViewColumn dc in RoomInfoDataGridView.Columns)
{
vr.Cells.Add(dc.CellTemplate.Clone() as DataGridViewCell);
vr.Cells[vr.Cells.Count - 1].Value = dr[dc.Name];
}
RoomInfoDataGridView.Rows.Add(vr);
}
// 設置RoomInfoDataGridView禁止根據列排序
int i;
for (i = 0; i < this.RoomInfoDataGridView.Columns.Count; i++) { }
this.RoomInfoDataGridView.Columns[--i].SortMode = DataGridViewColumnSortMode.NotSortable;
return true;
}
此外,記住不能用關鍵字(如“user”)作爲表和表中列的名字,否則你會很麻煩。
下面是我的界面(功能略顯單薄):
其實實驗做到什麼成度不重要,重要的是能提高自己的思考能力和代碼水平,從中有所收穫。