Sunday, May 24, 2015

[C#] PictureBox - 亂數產生圓

論壇問題,討論 Random class 使用,拿來練習

Random 產生相同值的 MSDN 說明
預設的種子值是從系統時鐘衍生而來,而且解析度有限。 因此,若在極短時間內連續呼叫預設建構函式,建立不同的 Random 物件,這些物件就會有完全相同的預設種子值,也就會產生完全相同的幾組亂數。 只要使用單一 Random 物件來產生所有的亂數,就可以避免這個問題。 您也可以解決它,方法是修改系統時鐘傳回的種子值,然後明確地提供這個新的種子值給 Random(Int32) 建構函式。
採用下列寫法來避免 Random 產生相同值
Random r = new Random(Guid.NewGuid().GetHashCode());

Friday, May 22, 2015

[C#] GridView 練習

論壇問題 - GridView 練習題,討論內還有大神的 Youtube 教學

問題說明

[C#] GridView 練習-1

[C#] GridView 練習-2

大神 YouTube 教學

Wednesday, May 20, 2015

工業電腦主機板著火

廠長回報工業用 PC 傳出濃濃的塑膠味且有看見煙飄出,一聽見描述直覺是 Power 燒掉,趕快過去把電腦搬回來檢測。

電源檢查器 OK,拆開外殼也沒有看見燒掉的部分,拿新 Power 對 PC 進行測試,一通電就看見主機板燒起來, 真的是一小團火焰在那燒,Orz

下圖紅框框就是起火點

主機板失火

處理事件簿:
  • 20150430:
    • 淘寶網上找到比較接近該主機板型號,一片 3,2000 元,暈
    • 工業電腦台灣代理商目前沒現貨,詢問德國總公司
  • 20150504:
    • 代理商回電告知德國公司,該主機板為設備廠商專有型號,只能直接跟廠商直接購買
    • 決定老方法處理,Ghost 到一般 PC 內來使用
  • 20150505:
    • 找台比較接近的主機,利用 Ghost 弄出一顆硬碟,確保原本硬碟不會在測試過程中破壞掉,Ghost 硬碟放上一般 PC 測試,可正常開機,解決硬體問題
    • 開啟工業軟體時,發現功能不完全,懷疑是 COM Port 通訊有問題
  • 20150510:
    • 工業軟體部分一直沒有搞定,原本以為是 COM Port 出問題,因此買了 IDE 的 COM Port 來外接和 COM Tester ,利用 Tester 來判斷是不是正常通訊,後來發現 COM Port 不是問題所在
  • 20150511:
    • 經過交叉測試,確定西門子通訊卡是正常,但卻沒有正常作動,卡上燈號理論上一開機就應該要亮燈,但卻沒有
    • 老大從軟體設定方面著手,有找相關設定,讓卡上燈號順利亮起來,且工業軟體上消失的功能,也都出現
  • 20150512:
    • 上線測試,沒問題,搞定
  • 20150513:
    • 維修商技術人員來電告知,剛好有其他廠商也遇上工業電腦主機板燒掉問題,想要系統移轉至一般 PC,德國原廠可以支援該移轉動作,想詢問我們要不要一起弄,沒想到我們已經搞定
    • 一張西門子通訊卡要 30,000 元,一開始懷疑它掛掉時,很擔心買不到
    • COM Tester 測試 COM Port 時,有發現到似乎不需要它,Tester 燈號完全沒有閃爍,詢問才知道,那是觸控螢幕用

Monday, May 18, 2015

[SQL] ISNULL() 回傳值

使用者回報說,報表列印功能,規格欄位資訊沒有顯示完全,從下圖就可以看見第四項資訊全部都被截斷

[SQL] ISNULL() 回傳值-2

從 TSQL 語法發現到規格資訊(Mt_Nam_Dim)是透過 ISNULL() 來判斷產生,原資料庫的資料是完整的,ISNULL() 回傳值就是問題所在
SELECT
    BD.BillNO,
    ID.MtCode,
    ISNULL(M.Mt_num, D.Mt_Num) AS Mt_Num,
    ISNULL(M.Mt_Nam_Dim,D.Spec) AS Mt_Nam_Dim,
    ID.RushQty,
    ID.RushPrice,
    ID.SubTotal
FROM PurchBillDetail AS BD
    JOIN PurchPayDetail AS PD ON BD.PNO = PD.PNO AND BD.RowNO = PD.RowNO
    JOIN PurchIn AS I ON PD.PINO = I.PINO
    JOIN PurchInDetail AS ID ON I.PINO = ID.PINO
    JOIN PurchDetail AS D ON ID.PurNO = D.PurNO AND ID.MtCode = D.MtCode
    LEFT JOIN MtData AS M ON ID.MtCode = M.MtCode
WHERE BD.BillNO = 'P1040518028'
MSDN ISNULL() 相關資訊
  • 語法:ISNULL ( check_expression , replacement_value )
  • 傳回類型:傳回與 check_expression 相同的類型。 如果提供了常值 NULL 做為 check_expression,就會傳回 replacement_value 的資料類型。 如果提供了常值 NULL 做為 check_expression 但是沒有提供任何 replacement_value,就會傳回 int。
  • 備註:如果 check_expression 值不是 NULL,便傳回這個值;否則,如果類型不同,便在 replacement_value 隱含地轉換成 check_expression 的類型之後,再傳回它。 如果 replacement_value 比 check_expression 長,replacement_value 可能會被截斷。
從備註中發現到線索,查欄位資料型態長度,發現分別
  • Mt_Nam_Dim:char(100)
  • Spec:varchar(500)
資料長度從 500 變成 100,規格說明也就被截斷,好細的小細節,Orz

修正 TSQL,在 ISNULL() 內強制把第一參數轉型為 varchar(500) 來避免這個問題
SELECT
    BD.BillNO,
    ID.MtCode,
    ISNULL(M.Mt_num, D.Mt_Num) AS Mt_Num,
    ISNULL
    (
        CAST(M.Mt_Nam_Dim AS varchar(500)),  -- char(100)
        D.Spec                               -- varchar(500)
    ) AS Mt_Nam_Dim,
    ID.RushQty,
    ID.RushPrice,
    ID.SubTotal
FROM PurchBillDetail AS BD
    JOIN PurchPayDetail AS PD ON BD.PNO = PD.PNO AND BD.RowNO = PD.RowNO
    JOIN PurchIn AS I ON PD.PINO = I.PINO
    JOIN PurchInDetail AS ID ON I.PINO = ID.PINO
    JOIN PurchDetail AS D ON ID.PurNO = D.PurNO AND ID.MtCode = D.MtCode
    LEFT JOIN MtData AS M ON ID.MtCode = M.MtCode
WHERE BD.BillNO = 'P1040518028'
下圖為正確顯示

[SQL] ISNULL() 回傳值-1

Friday, May 15, 2015

[SQL] sp_executesql 參數限制

在 Store Procedure 中,利用 sp_executesql 執行動態 TSQL 語法時,出現下面的錯誤訊息
程序必須有類型 'ntext/nchar/nvarchar' 的參數 '@statement'。
閱讀 MSDN 上發現,原來 sp_executesql 的第一、二個參數都必須是 Unicode
  • @stmt:Transact-SQL 陳述式或批次的 Unicode 字串。@stmt 必須是 Unicode 常數或 Unicode 變數。
  • @params:包含 @stmt 的所有內嵌參數定義的字串。 此字串必須是 Unicode 常數或 Unicode 變數。
USE [AdventureWorks2014]
GO

CREATE PROCEDURE [dbo].[uspQtyStat] 
(
    @StartDate date, 
    @EndDate date, 
    @ProdNO char(5) = '', 
    @Status nchar(4) = ''
)
AS
BEGIN

    SET NOCOUNT ON;

    DECLARE @TSQL varchar(max) -- 問題所在,不是 Unicode
 
    SET @TSQL = 
        'SELECT 
             ProdName , 
             ProdNO , 
             Status , 
             Area ,
             COUNT(*) AS Qty
         FROM GVPractice
         WHERE CreateDate BETWEEN @StartDate AND @EndDate'
 
    IF @ProdNO <> ''
        SET @TSQL += 
            '
            AND ProdNO = @ProdNO'

    IF @Status <> ''
        SET @TSQL +=
            '
            AND Status = @Status'
 
    SET @TSQL += 
        '
        GROUP BY ProdName , ProdNO , Status , Area'

    EXEC dbo.sp_executesql 
        @TSQL,
        N'@StartDate date, @EndDate date, @ProdNO char(5), @Status nchar(4)',
        @StartDate ,
        @EndDate ,
        @ProdNO ,
        @Status

END
GO

把 @TSQL 宣告為 nvarchar(max) 就可以執行