markdown
# 需求描述
因為要做重構,需要找出有哪些邏輯是藏在DTO裡面的,
但DTO類別檔又很多,不想一個個找
所以就想寫個console程式來撈
# 做法
首先把要撈的DLL跟他相依的DLL都複製到要執行的排程執行檔輸出資料夾(通常是bin\debug)
以下程式碼:
```
public class Worker
{
public void DoWork()
{
System.Reflection.Assembly service = Assembly.LoadFile(@"<你要找的namespace所在的dll的絕對路徑>.dll");
Type[] typelist = service.GetTypes();
var nameHaveDtoTypes = typelist.Where(x => x.Name.ToUpper().EndsWith("DTO"));//你的類別名稱的特徵,例如找DTO就結尾是DTO
foreach (var typeitem in nameHaveDtoTypes)
{
if(typeitem.GetProperties().Any(prop=> !MightBeCouldBeMaybeAutoGeneratedInstanceProperty(prop)))
{
foreach (var prop in typeitem.GetProperties().Where(prop => !MightBeCouldBeMaybeAutoGeneratedInstanceProperty(prop)))
{
//印到畫面跟輸出視窗
Console.WriteLine($"{typeitem.Name},{prop.Name}");
System.Diagnostics.Debug.WriteLine($"{typeitem.Name},{prop.Name}");
}
}
}
}
public bool MightBeCouldBeMaybeAutoGeneratedInstanceProperty(PropertyInfo info)
{
bool mightBe = info.GetGetMethod()
.GetCustomAttributes(
typeof(CompilerGeneratedAttribute),
true
)
.Any();
if (!mightBe)
{
return false;
}
bool maybe = info.DeclaringType
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.Name.Contains(info.Name))
.Where(f => f.Name.Contains("BackingField"))
.Where(
f => f.GetCustomAttributes(
typeof(CompilerGeneratedAttribute),
true
).Any()
)
.Any();
return maybe;
}
}
```
參考:
1.LINE群大神指點關鍵字**CompilerGeneratedAttribute**
這個是指在編譯成DLL時,單純getter setter的屬性上面會有這個tag
https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.compilergeneratedattribute.aspx
2.How to find out if a property is an auto-implemented property with reflection?
https://stackoverflow.com/questions/2210309/how-to-find-out-if-a-property-is-an-auto-implemented-property-with-reflection?lq=1
2018年8月9日 星期四
2017年12月4日 星期一
Kendo UI Grid + datasource 錯誤處理 | Kendo UI Grid datasource error handle
markdown
(我的Kendo版本是2017.3.913)
最常用的CRUD應用元件,KendoUI Grid + Datasource transport,
可以簡單串起Restful API,
但錯誤處理上有一些地方要注意
使用transport時API如果不拋出500或者404之類的錯誤,
而是用處理完成,但處理結果有誤,錯誤訊息放在一個字串屬性裡面的這種模式,
datasource無法去抓出那個物件秀出來,
這時就要用因為有錯誤所以要拋exception的概念,
讓API拋出HttpStatusCode.InternalServerError,
這樣前端ajax呼叫時就會抓到錯誤,
然後丟給datasource裡的error屬性事件處理,
就可以用e.xhr.responseJSON.Message抓出錯誤內容,
但也要加上undefined偵測,不是只有API邏輯錯的時候才會丟錯
所以error物件裡面也不是常常都有xhr
如果是自己寫的介面,例如另外寫kendo window,
並且自訂按鈕送出ajax,你就可以控制ajax的邏輯,
要用「有錯就是要拋錯」或者「你成功執行那就給我200,商業邏輯錯誤再另外包」
哪一種抓錯方式都可以處理了。
另外如果新增刪除修改的API用void類型,datasource的transport會拋一個JSON parsererror的錯,但若是給他回傳值,則不會有這個錯
我用的回傳物件格式:
```
public class OperationOutModel { ///執行結果
public bool result { get; set; }
///錯誤訊息
public string msg { get; set; }
}
```
(我的Kendo版本是2017.3.913)
最常用的CRUD應用元件,KendoUI Grid + Datasource transport,
可以簡單串起Restful API,
但錯誤處理上有一些地方要注意
使用transport時API如果不拋出500或者404之類的錯誤,
而是用處理完成,但處理結果有誤,錯誤訊息放在一個字串屬性裡面的這種模式,
datasource無法去抓出那個物件秀出來,
這時就要用因為有錯誤所以要拋exception的概念,
讓API拋出HttpStatusCode.InternalServerError,
這樣前端ajax呼叫時就會抓到錯誤,
然後丟給datasource裡的error屬性事件處理,
就可以用e.xhr.responseJSON.Message抓出錯誤內容,
但也要加上undefined偵測,不是只有API邏輯錯的時候才會丟錯
所以error物件裡面也不是常常都有xhr
如果是自己寫的介面,例如另外寫kendo window,
並且自訂按鈕送出ajax,你就可以控制ajax的邏輯,
要用「有錯就是要拋錯」或者「你成功執行那就給我200,商業邏輯錯誤再另外包」
哪一種抓錯方式都可以處理了。
另外如果新增刪除修改的API用void類型,datasource的transport會拋一個JSON parsererror的錯,但若是給他回傳值,則不會有這個錯
我用的回傳物件格式:
```
public class OperationOutModel { ///
2016年10月11日 星期二
c# oracle 撈不出資料 但developer撈有資料 | c# oracle can't get data but data can get when query on developer
環境:
VS2013& 類別庫專案 & C# & Oracle.DataAccess 4.121.1.0
情況:
在oracle developer跑一段select 有幾個變數
select blablabla from table where A=:A and B=:B and C=:C
執行結果有資料
但在C#用OracleDataReader撈到DataTable
dt.Load(odr)
撈出來卻沒資料
印出變數跟sql有正確,也沒有跳exception,
查DB的query log也沒看到有執行這段查詢....
解決:
後來發現是變數塞值的時候順序塞錯了
我寫的是
Parameters.Add("A",A)
Parameters.Add("C",C)
Parameters.Add("B",B)
但應該要照順序去塞入
Parameters.Add("A",A)
Parameters.Add("B",B)
Parameters.Add("C",C)
才可以正常的綁定變數
VS2013& 類別庫專案 & C# & Oracle.DataAccess 4.121.1.0
情況:
在oracle developer跑一段select 有幾個變數
select blablabla from table where A=:A and B=:B and C=:C
執行結果有資料
但在C#用OracleDataReader撈到DataTable
dt.Load(odr)
撈出來卻沒資料
印出變數跟sql有正確,也沒有跳exception,
查DB的query log也沒看到有執行這段查詢....
解決:
後來發現是變數塞值的時候順序塞錯了
我寫的是
Parameters.Add("A",A)
Parameters.Add("C",C)
Parameters.Add("B",B)
但應該要照順序去塞入
Parameters.Add("A",A)
Parameters.Add("B",B)
Parameters.Add("C",C)
才可以正常的綁定變數
標籤:
C#,
DataTable,
Oracle,
Oracle.DataAccess
2016年9月1日 星期四
C# 從Oracle db取多個DataTable結果回來 | C# get multi DataTable result from Oracle DB
參考文章:
http://stackoverflow.com/questions/6149836/filling-multiple-datatables-with-1-oraclecommand
簡單來說就是在db上用 SYS_REFCURSOR 輸出結果
用 open cursor for select的方式就可以把結果丟回來
C#端的程式寫法大致上同CALL SP的方式,
參數設定中輸出的資料集是用OracleDbType.RefCursor這個型別
http://stackoverflow.com/questions/6149836/filling-multiple-datatables-with-1-oraclecommand
簡單來說就是在db上用 SYS_REFCURSOR 輸出結果
用 open cursor for select的方式就可以把結果丟回來
C#端的程式寫法大致上同CALL SP的方式,
參數設定中輸出的資料集是用OracleDbType.RefCursor這個型別
2016年8月9日 星期二
c# 呼叫oracle sp 出現ora-06502 pl/sql 數字或值錯誤 character string buffer too small | c# call oracle sp get ora-06502
寫sp時遇到ora-06502 pl/sql 數字或值錯誤 character string buffer too small
出錯行數是在我的sp的設定輸出參數文字字串訊息那一行
查了一下後發現是c#端在設定輸出參數時要順便指定大小在第三個參數
oc.Parameters.Add("P_MSG", OracleDbType.NVarchar2, 256).Direction=ParameterDirection.Output;
不然預設的buffer好像很小,多塞幾個字就over了
出錯行數是在我的sp的設定輸出參數文字字串訊息那一行
查了一下後發現是c#端在設定輸出參數時要順便指定大小在第三個參數
oc.Parameters.Add("P_MSG", OracleDbType.NVarchar2, 256).Direction=ParameterDirection.Output;
不然預設的buffer好像很小,多塞幾個字就over了
2016年7月22日 星期五
C# 寫入Oracle 加入變數時出現ArgumentOutOfRangeException | C# insert Oracle db get ArgumentOutOfRangeException when add parameter
語言:C#
DLL:Oracle.DataAccess.Client; 4.121.1.0
在做新增資料時,插入一個常數整數變數,就出錯在那一行
private const int _DEFAULT_VALUE = 0;
OracleCommand oc = new OracleCommand();
oc.CommandText = "insert into Table1 (col1) values(:val1)";
oc.Parameters.Add("val1", _DEFAULT_VALUE);--這行出錯
得到ArgumentOutOfRangeException
Google找到一篇文章
http://brianseekford.com/wordpress/?p=100
說在插入0的時候也出錯了
有個解決辦法是這樣
oc.Parameters.Add("val1", (object)_DEFAULT_VALUE);
把變數轉型為object,結果就過了!
我想應該是驅動程式的BUG
20170510補記
自己又遇到同樣問題 狗回來這一篇
不過有新解法
oc.Parameters.Add(new OracleParameter(){
ParameterName=":FLAG",
Value=(short)0,
OracleDbType=OracleDbType.Int16
});
這樣的方式也是OK
DLL:Oracle.DataAccess.Client; 4.121.1.0
在做新增資料時,插入一個常數整數變數,就出錯在那一行
private const int _DEFAULT_VALUE = 0;
OracleCommand oc = new OracleCommand();
oc.CommandText = "insert into Table1 (col1) values(:val1)";
oc.Parameters.Add("val1", _DEFAULT_VALUE);--這行出錯
得到ArgumentOutOfRangeException
Google找到一篇文章
http://brianseekford.com/wordpress/?p=100
說在插入0的時候也出錯了
有個解決辦法是這樣
oc.Parameters.Add("val1", (object)_DEFAULT_VALUE);
把變數轉型為object,結果就過了!
我想應該是驅動程式的BUG
20170510補記
自己又遇到同樣問題 狗回來這一篇
不過有新解法
oc.Parameters.Add(new OracleParameter(){
ParameterName=":FLAG",
Value=(short)0,
OracleDbType=OracleDbType.Int16
});
這樣的方式也是OK
2016年3月9日 星期三
C# Oracle Client 執行多行SQL回傳影響列數為-1 | C# Oracle Client execute multiple line sql number of rows affected return -1
問題:
當執行多行ORACLE SQL、如BEGIN ...END,或者MERGE INTO等指令時會,
ExecuteNonQuery()都只會回傳-1,這樣就無法看出影響列數
解決方法參考
http://stackoverflow.com/questions/32138843/merge-query-returns-1-instead-of-number-of-rows-merged
原本的SQL加上一段
-----------
寫成int回傳方法時
舊的System.Data.OracleClient裡面我這樣寫轉換:
count = (int)p.Value;
是可以跑的,但在新的Oracle.DataAccess.Client裡面
我要這樣轉換
(參考: http://stackoverflow.com/questions/3026036/convert-oracleparameter-value-to-int32 )
當執行多行ORACLE SQL、如BEGIN ...END,或者MERGE INTO等指令時會,
ExecuteNonQuery()都只會回傳-1,這樣就無法看出影響列數
解決方法參考
http://stackoverflow.com/questions/32138843/merge-query-returns-1-instead-of-number-of-rows-merged
原本的SQL加上一段
:num := sql%rowcount;
且增加一個OUTPUT變數OracleCommand cmd = new OracleCommand(sql, myConnection);
var p = cmd.Parameters.Add(":num", OracleDbType.Int32, ParameterDirection.Output);
cmd.ExecuteNonQuery();
Console.WriteLine("Rows affected: " + p.Value);
執行之後讀取變數的值即可得到影響列數-----------
寫成int回傳方法時
舊的System.Data.OracleClient裡面我這樣寫轉換:
count = (int)p.Value;
是可以跑的,但在新的Oracle.DataAccess.Client裡面
我要這樣轉換
(參考: http://stackoverflow.com/questions/3026036/convert-oracleparameter-value-to-int32 )
Convert.ToInt32((decimal)(OracleDecimal)(cmd.Parameters["successCount"].Value))
轉換時才不會出現InvalidCastException
標籤:
C#,
merge into,
multiple line sql,
Oracle
2015年11月20日 星期五
asp.Net ObjectDataSource output parameter
一個查詢功能
有與DB溝通的Class,查詢方法會回拋DataTable
前端做GridView+ObjectDataSource
現在想要做後端驗證
驗證的方式是在傳入參數加入一個自訂類別 myValidClass的 output參數叫msg
在函式開頭就會先做驗證
有錯誤的時候msg的status屬性就會是false
並且msg的msg屬性會塞錯誤訊息
在網頁端的ODS加上
<asp:Parameter Type="Object" Direction="Output" Name="msg" />
並且加入OnSelected方法ods_Selected
<asp:ObjectDataSource runat="server" ID="ods" .... OnSelected="ods_Selected">
.cs端的ods_Selected方法
protected void ods_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
myValidClass msg = (myValidClass)e.OutputParameters["msg"];
if (!msg.status)
{
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alert", "alert('"+msg.msg+"');", true);
}
}
DB溝通class的方法
public DataTable search(string parameter1, out myValidClass msg)
{
DataTable dt=new DataTable();
//Do your validate method
msg=new myValidClass();
msg.status=true;
if(string.IsNullOrEmpty(parameter1))
{
msg.status=false;
msg.msg="參數1不可為空";
}
if(msg.status)
{
dt=db.getData(parameter1);
}
return dt;
}
這樣在做完查詢後ods_Selected方法就會檢查msg有沒有錯誤,
有錯誤就會alert錯誤訊息
2015年11月18日 星期三
[C#][擴充方法] 取得西元日期的民國年月日
/// <summary> 將西元日期轉民國日期 回傳 字串陣列[0]民國年YYY [1]月MM [2]日DD</summary>
/// <param name="datetime">要轉換的日期</param>
/// <returns>字串陣列[0]民國年YYY [1]月MM [2]日DD</returns>
public static string[] ToSimpleTaiwanDate(this DateTime datetime)
{
TaiwanCalendar taiwanCalendar = new TaiwanCalendar();
return new string[]{
taiwanCalendar.GetYear(datetime).ToString(),
datetime.Month.ToString().PadLeft(2,'0'),
datetime.Day.ToString().PadLeft(2,'0')};
}
/// <summary> 將西元日期轉民國日期 回傳 字串陣列[0]民國年YYY [1]月MM [2]日DD</summary>
/// <param name="datetime">要轉換的日期</param>
/// <returns>字串陣列[0]民國年YYY [1]月MM [2]日DD</returns>
public static string ToSimpleTaiwanDate_YYYMMDD(this DateTime datetime)
{
TaiwanCalendar taiwanCalendar = new TaiwanCalendar();
return
taiwanCalendar.GetYear(datetime).ToString()+
datetime.Month.ToString().PadLeft(2,'0')+
datetime.Day.ToString().PadLeft(2,'0');
}
標籤:
日期,
民國年,
西元年,
C#,
Extension Method
[C#][擴充方法] 取得日期的統一發票期別
/// <summary> 傳入日期傳出發票期別的兩個數字 [1 2] [3 4]...</summary>
/// <param name="datetime">要判斷的日期</param>
/// <returns> 整數陣列[0]期別第一個月份 [1]期別第二個月份 </returns>
public static int[] ToInvoiceMonthRange(this DateTime datetime)
{
//2 4 6 8...->餘0 ->[2-1,2][4-1,4]
//1 3 5 7...->餘1 ->[1,1+1][3,3+1]
return (datetime.Month % 2) == 0
? new int[] { datetime.Month - 1, datetime.Month }
: (datetime.Month % 2) == 1
? new int[] { datetime.Month, datetime.Month+1 }
: new int[] { 0, 0 };
}
標籤:
日期,
期別,
統一發票,
C#,
Extension Method
2015年10月30日 星期五
C# call AS400 RPG program
markdown
# 背景
因為有RPG程式老舊但一時間又不能轉出來,只能先靠程式去呼叫,
所以就用C#引用AS400元件去呼叫RPG,得到結果。
# 使用DLL
`C:\Program Files (x86)\IBM\Client Access\Shared\cwbx.dll`
# 加入參考的時候要注意內嵌 Interop 型別的問題
REF:http://blog.miniasp.com/post/2010/06/21/dot-net-4-Interop-type-cannot-be-embedded-Use-the-applicable-interface-instead.aspx
# 程式碼參考:
REF:http://forums.asp.net/t/1817332.aspx?calling+as400+programs+from+c+
```C#
using cwbx; public string getRPGProgramReturnValue(string functionName, string LibraryName, string ProgramName, ProgramParameters parameters, string outputParameterName, out CUDResult msg) { msg = new CUDResult(); string result = string.Empty; StringConverter stringConverter = new StringConverterClass(); AS400System system = new AS400System(); try { // 定義 AS400 連線資訊 system.Define("AS400"); system.UserID = "你的帳號"; system.Password = "你的密碼"; //注意:一定要是IP,用domain網址會跳一個"CWB4016 - cwbCO_SetIPAddressW 傳回錯誤碼 87"的錯誤 system.IPAddress = "你的伺服器IP"; system.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd); // 有連線才繼續 if (system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1) { // 宣告程式物件 連到系統 cwbx.Program program = new cwbx.Program(); program.LibraryName = LibraryName; program.ProgramName = ProgramName; program.system = system; // 呼叫程式 try { program.Call(parameters); } catch (Exception ex) { msg.status = false; msg.msg += "呼叫程式時發生錯誤:" + ex.Message + "\n"; if (system.Errors.Count > 0) { msg.msg += "呼叫程式時發生system錯誤:"; foreach (cwbx.Error error in system.Errors) { msg.status = false; msg.msg += error.Text + "\n"; } } if (program.Errors.Count > 0) { msg.msg += "呼叫程式時發生program錯誤:"; foreach (cwbx.Error error in program.Errors) { msg.status = false; msg.msg += error.Text + "\n"; } } } result = stringConverter.FromBytes(parameters[outputParameterName].Value); } else { msg.status = false; msg.msg += "無法連線到AS400 ServiceRemoteCmd\n"; } system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll); msg.status = true; } catch (Exception ex) { system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll); msg.status = false; msg.msg += "執行" + functionName + "時發生錯誤:" + ex.Message + "\n"; } return result; } ```
# 追記
20180530 在改寫舊程式時我把IP換成DOMAIN,因應管理要求,
結果就跳出一個`CWB4016 - cwbCO_SetIPAddressW 傳回錯誤碼 87`的錯誤,
研究了半天想說自己沒改什麼東西,google也查不到什麼,
回頭看自己改的東西才想到那個欄位是IP,該不會不能填網址,
就改回IP,就正常了,算踩到一個雷。
但他還有一個`IPAddressLookupMode`屬性,我是沒試過。
# 背景
因為有RPG程式老舊但一時間又不能轉出來,只能先靠程式去呼叫,
所以就用C#引用AS400元件去呼叫RPG,得到結果。
# 使用DLL
`C:\Program Files (x86)\IBM\Client Access\Shared\cwbx.dll`
# 加入參考的時候要注意內嵌 Interop 型別的問題
REF:http://blog.miniasp.com/post/2010/06/21/dot-net-4-Interop-type-cannot-be-embedded-Use-the-applicable-interface-instead.aspx
# 程式碼參考:
REF:http://forums.asp.net/t/1817332.aspx?calling+as400+programs+from+c+
```C#
using cwbx; public string getRPGProgramReturnValue(string functionName, string LibraryName, string ProgramName, ProgramParameters parameters, string outputParameterName, out CUDResult msg) { msg = new CUDResult(); string result = string.Empty; StringConverter stringConverter = new StringConverterClass(); AS400System system = new AS400System(); try { // 定義 AS400 連線資訊 system.Define("AS400"); system.UserID = "你的帳號"; system.Password = "你的密碼"; //注意:一定要是IP,用domain網址會跳一個"CWB4016 - cwbCO_SetIPAddressW 傳回錯誤碼 87"的錯誤 system.IPAddress = "你的伺服器IP"; system.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd); // 有連線才繼續 if (system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1) { // 宣告程式物件 連到系統 cwbx.Program program = new cwbx.Program(); program.LibraryName = LibraryName; program.ProgramName = ProgramName; program.system = system; // 呼叫程式 try { program.Call(parameters); } catch (Exception ex) { msg.status = false; msg.msg += "呼叫程式時發生錯誤:" + ex.Message + "\n"; if (system.Errors.Count > 0) { msg.msg += "呼叫程式時發生system錯誤:"; foreach (cwbx.Error error in system.Errors) { msg.status = false; msg.msg += error.Text + "\n"; } } if (program.Errors.Count > 0) { msg.msg += "呼叫程式時發生program錯誤:"; foreach (cwbx.Error error in program.Errors) { msg.status = false; msg.msg += error.Text + "\n"; } } } result = stringConverter.FromBytes(parameters[outputParameterName].Value); } else { msg.status = false; msg.msg += "無法連線到AS400 ServiceRemoteCmd\n"; } system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll); msg.status = true; } catch (Exception ex) { system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll); msg.status = false; msg.msg += "執行" + functionName + "時發生錯誤:" + ex.Message + "\n"; } return result; } ```
# 追記
20180530 在改寫舊程式時我把IP換成DOMAIN,因應管理要求,
結果就跳出一個`CWB4016 - cwbCO_SetIPAddressW 傳回錯誤碼 87`的錯誤,
研究了半天想說自己沒改什麼東西,google也查不到什麼,
回頭看自己改的東西才想到那個欄位是IP,該不會不能填網址,
就改回IP,就正常了,算踩到一個雷。
但他還有一個`IPAddressLookupMode`屬性,我是沒試過。
標籤:
AS400,
C#,
cwbx.dll,
RPG program
2015年9月24日 星期四
NPOI write to Stream get Can't open closed Stream error
用NPOI寫EXCEL檔案
然後轉成串流,再轉乘Attachment給Email夾帶
但是一直發生無法存取關閉的串流錯誤
爬到這篇
http://www.codeproject.com/Tips/813187/Csharp-Read-and-Write-Excel-xls-and-xlsx-Files-Con
底下的留言
他先把串流轉byte 再開新串流byte轉串流
試了一下後果然可以了
但效能上如何就沒測了
然後轉成串流,再轉乘Attachment給Email夾帶
但是一直發生無法存取關閉的串流錯誤
爬到這篇
http://www.codeproject.com/Tips/813187/Csharp-Read-and-Write-Excel-xls-and-xlsx-Files-Con
底下的留言
他先把串流轉byte 再開新串流byte轉串流
試了一下後果然可以了
但效能上如何就沒測了
var arrBites = stream.ToArray();
MemoryStream newStream = new MemoryStream(arrBites);
標籤:
匯出excel,
asp.NET,
Attachment,
C#,
Email,
File,
MemoryStream,
NPOI,
SMTP,
Stream
2015年7月14日 星期二
System.Data.OracleClient與Oracle.DataAccess的變數問題
System.Data.OracleClient跟Oracle.DataAccess.dll 好像對變數的處理不一樣
我有一個查詢語法,日期處理是
跳出ORA-01008 : Not all variables bound
我要把後面的變數換個名稱,加入兩次變數,才能正常執行
我有一個查詢語法,日期處理是
DATE between to_date(:DATE || ' 00:00:00','yyyy-mm-dd hh24:mi:ss') and TO_DATE(:DATE || ' 23:59:59','yyyy-mm-dd hh24:mi:ss')
在用前者的時候變數只需要加入一次
Command.Parameters.Add(new OracleParameter("DATE", DATE));
但在用後者的時候,後面那個變數會被認為未給值,跳出ORA-01008 : Not all variables bound
我要把後面的變數換個名稱,加入兩次變數,才能正常執行
DATE between to_date(:DATE || ' 00:00:00','yyyy-mm-dd hh24:mi:ss') and TO_DATE(:DATE2 || ' 23:59:59','yyyy-mm-dd hh24:mi:ss')
Command.Parameters.Add(new OracleParameter("DATE", DATE));
Command.Parameters.Add(new OracleParameter("DATE2", DATE));
不過同樣的sql在oracle sql developer執行,他也只會要我輸入一次變數值就是了
2015年6月18日 星期四
WEB METHOD JSON MAX LENGTH
使用JSON.NET來轉換物件為JSON
STRING出來了但是WEBMETHOD丟出去時說太大
在WEB.CONFIG加入此設定值就可以提高上限了
STRING出來了但是WEBMETHOD丟出去時說太大
在WEB.CONFIG加入此設定值就可以提高上限了
<configuration>
<system .web.extensions="">
<scripting>
<webservices>
<jsonserialization maxjsonlength="2147483644">
</jsonserialization></webservices>
</scripting>
</system>
</configuration>
標籤:
asp.NET,
C#,
JSON.NET,
JsonMaxLength
2015年6月8日 星期一
2015年5月22日 星期五
ORACLE在C# 執行多行指令的方法
我要刪除一個資料,順便刪除相關的資料表中屬於此資料SID的資料
但是一直執行SQL也很煩,找了可以一次執行多行的寫法
重點是要用分號隔開
StringBuilder sb = new StringBuilder();
sb.Append(@"BEGIN
delete from table1 where SID=:SID ;
delete from table2 where SID=:SID ;
delete from table3 where SID=:SID ;
delete from table4 where SID=:SID ;
delete from table5 where SID=:SID ;
END;
");
try
{
cnn.Open();
using (OracleCommand cmm = new OracleCommand(sb.ToString(), cnnTSTM))
{
cmm.Parameters.Clear();
cmm.Parameters.Add(new OracleParameter("SID", SID));
cmm.ExecuteNonQuery();
}
cnn.Close();
}
但是一直執行SQL也很煩,找了可以一次執行多行的寫法
重點是要用分號隔開
StringBuilder sb = new StringBuilder();
sb.Append(@"BEGIN
delete from table1 where SID=:SID ;
delete from table2 where SID=:SID ;
delete from table3 where SID=:SID ;
delete from table4 where SID=:SID ;
delete from table5 where SID=:SID ;
END;
");
try
{
cnn.Open();
using (OracleCommand cmm = new OracleCommand(sb.ToString(), cnnTSTM))
{
cmm.Parameters.Clear();
cmm.Parameters.Add(new OracleParameter("SID", SID));
cmm.ExecuteNonQuery();
}
cnn.Close();
}
2015年5月11日 星期一
用ExchangeService API (EWS) 確認EMAIL信箱位址是否存在
string sResult = "";
List<string> emailCollect = new List<string>();
ExchangeService es = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
es.Credentials = new System.Net.NetworkCredential("ACCOUNT", "PASSWORD", "NETAREA");
es.Url = new Uri("https://MYWEBSITE/ews/Exchange.asmx");
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var resolvedNames = es.ResolveName("想找的姓名或帳號");
foreach (var resolvedName in resolvedNames)
{
emailCollect.Add(resolvedName.Mailbox.Address);
}
if (emailCollect.Count > 0)
{
sResult = emailCollect[0].ToString().Trim();
Console.WriteLine(sResult);
}
else
Console.WriteLine("找不到信箱!");
List<string> emailCollect = new List<string>();
ExchangeService es = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
es.Credentials = new System.Net.NetworkCredential("ACCOUNT", "PASSWORD", "NETAREA");
es.Url = new Uri("https://MYWEBSITE/ews/Exchange.asmx");
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var resolvedNames = es.ResolveName("想找的姓名或帳號");
foreach (var resolvedName in resolvedNames)
{
emailCollect.Add(resolvedName.Mailbox.Address);
}
if (emailCollect.Count > 0)
{
sResult = emailCollect[0].ToString().Trim();
Console.WriteLine(sResult);
}
else
Console.WriteLine("找不到信箱!");
標籤:
找信箱是否存在,
C#,
EWS,
ExchangeService
2015年5月5日 星期二
RDLC 文字方塊 增大 超出
發現一張表的文字方塊有的超出寬度與高度後會撐大,
有的只會換行然後超出邊界的部分就截掉
解決方式
文字方塊右鍵→屬性→一般頁面裡的[調整大小選項]把允許高度增加給取消打勾就好了
有的只會換行然後超出邊界的部分就截掉
解決方式
文字方塊右鍵→屬性→一般頁面裡的[調整大小選項]把允許高度增加給取消打勾就好了
2015年3月31日 星期二
SPA專案架構
MVC書一次都教一堆東西...
RAZOR語法、實體資料庫模型、LINQ語法、IENUMERABLE型態...
實在有點懶的學
20150403補充:原來這個叫做SPA架構
前輩教的類MVC架構
1.Modal-就只是個Modal,放屬性欄位而已
2.DAL-資料庫存取相關功能(Data Access Level)
3.主要專案-前端功能
應用在網站專案、Console專案、winform等等都可
1.Visuao Studio建立空白解決方案
2.建立類別庫專案-Modal,想到再加入類別即可
3.建立類別庫專案-DAL
4.建立主要專案,以一般ASP.NET網站專案為例
網站專案加入參考Modal與DAL
DAL加入Modal參考
Modal不參考任何專案,獨立
5.假設要做一個客戶主檔維護功能,有新增刪除修改顯示(CRUD)基本功能
客戶主檔資料表:
SID、客戶名稱、客戶電話三個欄位就好
Modal底下建立客戶主檔類別
public class Customer
{
///<summary>流水號</summary>
public int SID{get;set;}
///<summary>客戶名稱</summary>
public string Name {get;set;}
///<summary>客戶電話</summary>
public string PhoneNumber {get;set;}
}
新增、更新、刪除時的訊息類別
public class msgCRUD
{
public static const string STATUS_SUCCESS="success";
public static const string STATUS_ERROR="error";
public string status {get;set;}
public string msg {get;set;}
}
DAL底下建立類別
using Modal;
public class CustomerController
{
public List<Customer> searchData(out msgCRUD msg)
{
msg=new msgCRUD();
List<Customer> list=new List<Customer>();
DataTable dt=new DataTable();
try
{
//資料庫處理,結果塞到DataTable
if(dt.Rows.Count>0)
{
foreach(DataRow dr in dt.Rows)
{
list.Add(new Customer(){
SID = dr["SID"].ToString(),
Name = dr["Name"].ToString(),
PhoneNumber = dr["PhoneNumber"].ToString()
});
}
}
}
catch(Exception ex)
{
msg.status=msgCRUD.STATUS_ERROR;
msg.msg="搜尋時發生錯誤:"+ex.ToString();
}
return list;
}
}
網站專案底下建立ASP網頁
後端Customer.aspx.cs
[WebMethod]
protected string searchData()
{
CustomerController cc=new CustomerController();
List<Customer> list=cc.searchData();
string myJson=JsonConvert.SerializeObject(list);
return myJson;
}
前端Customer.aspx
使用JQuery AJAX語法取得資料
...
</form>
<script type="javascript">
function searchData()
{
if (!window.ajaxValidPass) {
var sdata = { };
$.ajax({
type: "POST",
async: true,
url: "Customer.aspx/searchData",
data: JSON.stringify(sdata),
contentType: "application/json; charset=UTF-8",
dataType: 'json',
success: function (data) {
var ary = $.parseJSON(data.d);
if (ary) {
//處理撈回來的東西
}
else {
alert('找不到資料');
}
}
},
error: function (response) {
console.log('error:' + response.responseText);
alert('error:' + response.responseText);
}
});
}
}
</script>
到此即為基本的前端到後端,後端到資料存取層的資料傳輸方式
可以擺脫Server Control夾帶的垃圾CODE
又可以保持架構上的彈性
RAZOR語法、實體資料庫模型、LINQ語法、IENUMERABLE型態...
實在有點懶的學
20150403補充:原來這個叫做SPA架構
前輩教的
1.Modal-就只是個Modal,放屬性欄位而已
2.DAL-資料庫存取相關功能(Data Access Level)
3.主要專案-前端功能
應用在網站專案、Console專案、winform等等都可
1.Visuao Studio建立空白解決方案
2.建立類別庫專案-Modal,想到再加入類別即可
3.建立類別庫專案-DAL
4.建立主要專案,以一般ASP.NET網站專案為例
網站專案加入參考Modal與DAL
DAL加入Modal參考
Modal不參考任何專案,獨立
5.假設要做一個客戶主檔維護功能,有新增刪除修改顯示(CRUD)基本功能
客戶主檔資料表:
SID、客戶名稱、客戶電話三個欄位就好
Modal底下建立客戶主檔類別
public class Customer
{
///<summary>流水號</summary>
public int SID{get;set;}
///<summary>客戶名稱</summary>
public string Name {get;set;}
///<summary>客戶電話</summary>
public string PhoneNumber {get;set;}
}
新增、更新、刪除時的訊息類別
public class msgCRUD
{
public static const string STATUS_SUCCESS="success";
public static const string STATUS_ERROR="error";
public string status {get;set;}
public string msg {get;set;}
}
DAL底下建立類別
using Modal;
public class CustomerController
{
public List<Customer> searchData(out msgCRUD msg)
{
msg=new msgCRUD();
List<Customer> list=new List<Customer>();
DataTable dt=new DataTable();
try
{
//資料庫處理,結果塞到DataTable
if(dt.Rows.Count>0)
{
foreach(DataRow dr in dt.Rows)
{
list.Add(new Customer(){
SID = dr["SID"].ToString(),
Name = dr["Name"].ToString(),
PhoneNumber = dr["PhoneNumber"].ToString()
});
}
}
}
catch(Exception ex)
{
msg.status=msgCRUD.STATUS_ERROR;
msg.msg="搜尋時發生錯誤:"+ex.ToString();
}
return list;
}
}
網站專案底下建立ASP網頁
後端Customer.aspx.cs
[WebMethod]
protected string searchData()
{
CustomerController cc=new CustomerController();
List<Customer> list=cc.searchData();
string myJson=JsonConvert.SerializeObject(list);
return myJson;
}
前端Customer.aspx
使用JQuery AJAX語法取得資料
...
</form>
<script type="javascript">
function searchData()
{
if (!window.ajaxValidPass) {
var sdata = { };
$.ajax({
type: "POST",
async: true,
url: "Customer.aspx/searchData",
data: JSON.stringify(sdata),
contentType: "application/json; charset=UTF-8",
dataType: 'json',
success: function (data) {
var ary = $.parseJSON(data.d);
if (ary) {
//處理撈回來的東西
}
else {
alert('找不到資料');
}
}
},
error: function (response) {
console.log('error:' + response.responseText);
alert('error:' + response.responseText);
}
});
}
}
</script>
到此即為基本的前端到後端,後端到資料存取層的資料傳輸方式
可以擺脫Server Control夾帶的垃圾CODE
又可以保持架構上的彈性
2015年3月27日 星期五
LOG功能
public void myLog(string format, params object[] arg)
{
myLog(string.Format(format, arg));
}
/// <summary> log寫入text檔案 </summary>
/// <param name="message"></param>
public void myLog(string message)
{
//取得執行檔案(BIN/DEBUG)的路徑,加上LOG資料夾形成完整路徑
string loaclpath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string path = Path.Combine(Path.GetFullPath(loaclpath), "log");
if (string.IsNullOrEmpty(path))
{
path = Directory.GetCurrentDirectory();
}
string filename = Path.Combine(path, string.Format("{0:yyyy}\\{0:MM}\\{0:yyyy-MM-dd}.txt", DateTime.Now));
FileInfo finfo = new FileInfo(filename);
if (finfo.Directory.Exists == false)
{
finfo.Directory.Create();
}
string writeString = string.Format("[{0:yyyy/MM/dd HH:mm:ss}] {1}",
DateTime.Now, message) + Environment.NewLine;
File.AppendAllText(filename, writeString, Encoding.Unicode);
}
{
myLog(string.Format(format, arg));
}
/// <summary> log寫入text檔案 </summary>
/// <param name="message"></param>
public void myLog(string message)
{
//取得執行檔案(BIN/DEBUG)的路徑,加上LOG資料夾形成完整路徑
string loaclpath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string path = Path.Combine(Path.GetFullPath(loaclpath), "log");
if (string.IsNullOrEmpty(path))
{
path = Directory.GetCurrentDirectory();
}
string filename = Path.Combine(path, string.Format("{0:yyyy}\\{0:MM}\\{0:yyyy-MM-dd}.txt", DateTime.Now));
FileInfo finfo = new FileInfo(filename);
if (finfo.Directory.Exists == false)
{
finfo.Directory.Create();
}
string writeString = string.Format("[{0:yyyy/MM/dd HH:mm:ss}] {1}",
DateTime.Now, message) + Environment.NewLine;
File.AppendAllText(filename, writeString, Encoding.Unicode);
}
訂閱:
文章 (Atom)