用精靈在做出的Server端dll,如何在讀取資料時能有排序或條件篩選功能,SQL語句封裝在哪里呢?
說明如下:
(1).資料(SQL語句)的封裝在Server Module中的InfoCommand控件中。
(2).排序可以寫在InfoCommand中,如直接寫Order By,但不可由User變更,或是在Client端使用InfoBidingSource.Sort()方式來排序。
(3).如要使用動態條件,可以使用InfoDataSet.SetWhere()的方式來動態改變SQL的Where語句。
使用存儲過程提取大量數據,在Client客戶端介面執行發生超時的錯誤, 請問應該如何解決?
InfoCommand以Stored Procedure中去取資料時,如果需處理很久,則會發生超時的現象,可以在InfoCommand的CommandTimeOut屬性中來設置超時時間。
如果Table中有使用uid的欄位,則在資料存檔時出現[資料行]uid不屬於某個TABLE的錯誤, 如何解決?
1)請檢查:在UpdateComp的FieldAttrs內不應該有UID這個欄位,如果有,請刪除。
2)在InfoCommand中,是否有select uid欄位進去,如果沒有,請加進去。因為在存檔的時候,程式去取得SchemaTable的時候會自動把資料庫中的Key欄位也一同取下來,而程式去取異動行的時候只取到了其他欄位,所以在匹配欄位的時候就會發生錯誤。
UpdateComponent的BeforeDelete如何取消刪除?
兩種方法,請參考:
1)如果您是要判斷哪些資料可以刪除哪些不可以,您可以在Client端的BeforeCommand事件中處理,比較簡單。
2)如果是必須要在Server處理的,您需要BeforeDelete事件中寫:
if (Convert.Toint16(UpdateComp1.GetFieldOldValue("Qty"))<=0) // 條件成立的話
{
throw new Exception("yourMessage"); //拋出異常與訊息
}
然後需要在Client的InfoDataSet的ApplyError事件中接收:
if (e.Exception.InnerException.Message == "yourMessage")
{
MessageBox.Show("yourMessage"); //可以自行改變訊息
e.Cancel = true; //讓系統知道後端有錯誤
}
如何在UpdateComp中去決定存入資料庫的內容值?
在UpdateComp的處理事件中(如BeforeInsert/BeforeModify等),如果需要去決定欄位的內容值,可以使用UpdateComp.SetFieldValue(FieldName,Value)方式來設定,但是SetFieldValue()的欄位對象必須是在InfoCommand存在的欄位,否則會發生錯誤,以下是自動決定更改的使用者與時間的範例:
private void ucOrders_BeforeModify(object sender, UpdateComponentBeforeModifyEventArgs e)
{
ucOrders.SetFieldValue("UpdatedUser",this.GetClientInfo(ClientInfoType.LoginUser);
ucOrders.SetFieldValue("UpdatedDate",System.DateTime.Today);
}
如何在UpdateComp的事件中去自行處理其他資料交易,而不必使用InfoTransaction元件?
在UpdateComp中的事件中,可以使用GetFieldCurrentValue()與GetFieldOldValue()來讀取Client所輸入的欄位新舊值,並透過ExecuteCommand()來自行下出SQL語法,為了讓此SQL命令能配合原來UpdateComp的Transaction須為同一個交易(同步Commit或RollBack),因此可以透過UpdateComp取得此Connection與Transaction,舉例如下:
int QtyOld = UpdateComp1.GetFieldOldValue("Qty");
int QtyNew = UpdateComp1.GetFieldCurrentValue("Qty");
this.ExecuteCommand("update table2 set field = ....", UpdateComp1.conn, UpdateComp1.trans);
需要注意的地方,新增時只能用GetFieldCurrentValue,刪除的時候,只能用GetFieldOldValue。
在新增時,UpdateComp中使用GetFieldOldValue時,系統報錯。錯誤訊息:沒有可存取的 Original 資料.! ,這是為甚麼?
在UpdateComp的新增時,因為UpdateCom中並沒有各欄位的舊值內容,在新增的事件中,是不能使用GetFieldOldValue的方法。
UpdateComponent 中FieldAttrs屬性會應用在哪裡?
FieldAttrs是為了給特殊功能使用的,並不是一定都須設定的,沒有設定也一樣可以正常insert或者update,一般的用法有:
1. 給某個欄位預設值,這個值不一定需要在Client端顯示,比如更改者,更改時間等等。
2. 是否需要回寫此欄位元,比如有些left join進來的欄位是不能回寫到資料庫的,可以在此設定不存檔,也有一些為了顯示用的計算欄位等等,都是同樣的用法。
3. 還可以定義是否需要checknull.不過,這個功能更多的是在Client端使用DefaultValidate或WebValidate來實現,畢竟到了後端確實時機晚了一些。
當該Table有設定後端資料庫的Trigger時,可能會出現多筆資料被異動錯誤,請問應該如何解決?
在UpdateComp在存檔的時候EEP會去判斷資料受到影響的筆數,也就是說只能有一筆資料影響才會是正確的交易,如果超過一筆或沒有資料被影響,這都是會被認為是錯誤的交易,所以才會出現上述問題。在EEP SP3之後的UpdateComp元件,增加了一個屬性RowAffectCheck,可以將其設為false,這樣系統就不會去檢查這個影響筆數。
在infocommand裡,當更新table裡面的值時,要如何同時更新另外一個table的資料?
方式一.在UpdateComponent的相關事件寫程式下insert or update的sql語句(為了包在同一個Transaction請在調用ExecuteSql或者ExecuteCommand方式時使用updateComp的conn和trans)。方式二.傳參數方式
錯誤訊息:的KeyField[Srvtools.KeyItem]欄位不存在?
如果有Left join的欄位,請將Left Join的欄位放在sql語句的後半部分,比如:
select Orders.*, CompanyName from Orders left join Customers on ......
不要寫成:select CompanyName, Orders.* from Orders left join Customers on ......
使用InfoTransaction元件,希望符合條件再執行過帳
InfoTransaction元件有BeforeTrans事件,可以通過e.Cancel=true來取消。
InfoTransaction的BeforeTrans事件裡,該如何取得Client輸入的資料?
在BeforeTrans事件中可以通過UpdateComp.CurrentRow來讀到當前的Row, 如下:
private void infoTransaction1_BeforeTrans(object sender, InfoTransactionBeforeTransEventArgs e)
{
int i = Convert.ToInt16(ucMaster.CurrentRow["Quantity"]); // 取得 ucMaster所對應的Quantity欄位值
….
}
server如何使用StoredProcedure?
只要使用InfoCommand元件即可呼叫StoredProcedure,將InfoCommand的CommandType設定為StoredProcedure,並以CommandText來設定StoredProcedure的名稱,然後利用InfoParameters建立StoredProcedure所要傳遞的參數即可,網站下載區中有專門的參考文件,如下:
http://www.infolight.com.tw/download/file/InfoCommand%E4%BD%BF%E7%94%A8%E5%AD%98%E5%84%B2%E9%81%8E%E7%A8%8B.doc
如何在Server端使用StoredProcedure查詢?錯誤訊息:找不到預存程式 'SP_GET_USERSTOLIST?
在InfoCommand的CommandText只能填入你的預存程式名稱,而不是整個sql語句,如:
CommandText=SP_GET_USERSTOLIST
CommandType=StoredProcedure
InfoParameters建立一InfoParameters,ParameterName=UserID
ServiceManager要註冊一function專門呼叫此InfoCommand回傳object,就可以調用成功了
更多詳情,請參考
http://www.infolight.com.tw/download/file/InfoCommand%E4%BD%BF%E7%94%A8%E5%AD%98%E5%84%B2%E9%81%8E%E7%A8%8B.doc
如何在server上抓取當前login的User.
直接寫使用object[] user_id = this.GetClientInfo(ClientInfoType.LoginUser);
This是指DataModule這個Clasee,在Server端都是以DataModule這個Class為範圍的。
寫了一個ServerMethod後始終在return傳回後,發生錯誤?
在Server Method Return值時,其陣列的第一個參數一定必須傳回0, (如 ret[0] 必須是0),這是EEP系統用的返回參數,0代表正常執行,1代表有錯誤發生,因此,如果你傳為不是0的值,系統都會認為發生了錯誤,但從第二個參數開始,你可以自由使用。
何時該使用 Server Method,使用 server method 有什麼好處?
ServerMethod提供的是一種架構,非常自由,比如可以傳遞任意參數,可以返回任意結果,可以完成很多功能。因為在N-Tier架構中,不管是Windows Client還是IIS Server都不應該可以直接連線到Database Server才對(基於安全與流量管制理由),因此Client端要處理大量的資料或用程式自由存取資料庫,就必須藉由Server Method來處理,因此Server Method就好像Web Service一樣,提供所需的資料或商業邏輯的處理服務等等。至於什麼時候需使用Server Method,一般像大量資料的統計或者月結(年結)等都比較適合,這樣可以避免大量資料在server與client之間的傳輸。還有一些不需要client編輯操作的功能都可以放在server端用serverMethod來包裝處理。總之,Server Method用來處理與資料庫有關的商業邏輯,將U/I分離,因此Server Method也是一種SOA的架構之一。
Async call back後show另一form會當掉
源碼如下:
public void p_rod052_back(object[] oret1)
{
string repn = "rod052";
cr070v.Form1 temp = new cr070v.Form1();
temp.repn = repn;
temp.MdiParent = this.MdiParent;
temp.WindowState = FormWindowState.Maximized;
temp.Show();
}
異步呼叫與Form的show是有沖突.
以上述例子來看,解決方法:
1. 在public void p_rod052_back(object[] oret1)上面加一行程式:
public delegate void ShowForm();//定義一個委託
2. 原public void p_rod052_back(object[] oret1)改為:
{
ShowForm call = delegate()
{
string repn = "rod052";
cr070v.Form1 temp = new cr070v.Form1();
temp.repn = repn;
temp.MdiParent = this.MdiParent;
temp.WindowState = FormWindowState.Maximized;
temp.Show();
}
this.Invoke(call);
}
如何取得並顯示當前登入人數?
在Server上ServerConfig.UserLoginCount就是當前的登錄人數,可以通過ServerMethod來返回這個值.如:
Client端
object[] ret = CliUtils.CallMethod("S001", "GetUserCount", null);
Label1.Text = ret[1].ToString();
Server端
public object[] GetUserCount(object[] param)
{
return new object[]{0, ServerConfig.UserLoginCount};
}