星期二, 8月 29, 2023

[C#] Form 傳值 - 事件回傳

在 Line 社群上看見討論,使用事件 (Event) 來收回傳值,以筆記 - [C#] Form 傳值 為範本,再進行延伸

frmMain C# Code
namespace WindowsFormsApplication1
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {

        }

        private void btnCustSearch_Click(object sender, EventArgs e)
        {
            ClearControlValue();
            frmCustSearch CustSearch = new frmCustSearch();
            // 註冊 PassRetValue Event            
            CustSearch.PassRetValue += CustSearch_PassRetValue;
            CustSearch.ShowDialog();
        }

        private void CustSearch_PassRetValue(object sender, RetValueEventArgs e)
        {
            var customer = e.Customer;
            txtCustID.Text = customer.CustID.ToString();
            txtCustName.Text = customer.CustName;
            txtAddress.Text = customer.Address;
        }

        void ClearControlValue()
        {
            foreach (Control ctl in Controls.OfType<TextBox>())
            {
                if ((ctl is TextBox txt) == false)
                    continue;

                txt.Text = string.Empty;
            }
        }
    }
}
frmCustSearch C# Code
namespace WindowsFormsApplication1
{
    // 宣告 RetValueEventArgs
    public class RetValueEventArgs : EventArgs
    {
        public Customer Customer { get; private set; }

        public RetValueEventArgs(Customer customer)
        {
            Customer = customer;
        }
    }

    // 宣告 RetValueEventHandler delegate
    public delegate void RetValueEventHandler(object sender, RetValueEventArgs e);

    public partial class frmCustSearch : Form
    {
        public frmCustSearch()
        {
            InitializeComponent();
        }

        // 宣告 PassRetValue event 並透過它回傳
        public event RetValueEventHandler PassRetValue;

        private void frmCustSearch_Load(object sender, EventArgs e)
        {
            dgvCustomer.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            btnOK.Click += btn_Click;
            btnCancel.Click += btn_Click;
            dgvCustomer.DataSource = DataGridViewSource();
            dgvCustomer.ClearSelection();
        }

        List<Customer> DataGridViewSource()
        {
            return
                new List<Customer>()
                    {
                        new Customer() { CustID = 1, CustName = "客戶1", Address = "台北" },
                        new Customer() { CustID = 2, CustName = "客戶2", Address = "台中" },
                        new Customer() { CustID = 3, CustName = "客戶3", Address = "高雄" }
                    };
        }

        void btn_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            if (btn == null)
                return;

            DialogResult = DialogResult.OK;
            if (btn.Name == btnCancel.Name)
            {
                DialogResult = DialogResult.Cancel;
                return;
            }

            var customer = new Customer()
            {
                CustID = (int)dgvCustomer.CurrentRow.Cells[ColCustID.Name].Value,
                CustName = (string)dgvCustomer.CurrentRow.Cells[ColCustName.Name].Value,
                Address = (string)dgvCustomer.CurrentRow.Cells[ColAddress.Name].Value
            };

            var arg = new RetValueEventArgs(customer);
            // 觸發 PassRetValue event            
            PassRetValue?.Invoke(this, arg);

            Close();
        }
    }
}

星期五, 8月 25, 2023

[Azure Pipeline] 使用 Key Vault Secrets - 2

延續 [Azure Pipeline] 使用 Key Vault Secrets - 1 文章內容

Pipeline 內讀取 Secrets 並放進 txt 檔案內

Step1:Azure DevOps 建立 pipeline


星期四, 8月 24, 2023

[Azure Pipeline] 使用 Key Vault Secrets - 1

根據
來學習如何在 Pipeline 中使用 Key Vault Secrets,區分為下述兩大步驟
  • 建立 Key Vault 並設定 Secrets
  • Pipeline 內讀取 Secrets 並放進 txt 檔案內

建立 Key Vault 並設定 Secrets

Step1:Azure Portal => 建立資源 (紅線) 


星期日, 8月 20, 2023

[SQL] 重置 identity

Line 社群上討論,讀官方文件 - DBCC CHECKIDENT 才發現,原來 DBCC CheckIdent 除了查詢目前 identity 跑到哪外,還有可以進行重置動作,以下模擬問題弄個簡易範例來紀錄

DBCC CheckIdent 重置參數

RESEED 參數
Specifies that the current identity value should be changed.
new_reseed_value 參數
The new value to use as the current value of the identity column.
模擬問題的 TSQL 範例
DROP TABLE IF EXISTS tblIdentity

CREATE TABLE [dbo].[tblIdentity](
	[ID] [int] IDENTITY(100,1) NOT NULL, -- 不是從 1 開始跑
	[ExecuteTime] [datetime] NULL,
 CONSTRAINT [PK_tblIdentity] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

-- insert 5 筆資料
INSERT INTO tblIdentity (ExecuteTime) VALUES(GETDATE())
GO 5

-- 重置:從 0 開始跑
DBCC CheckIdent('tblIdentity', RESEED, 0)

-- 再 insert 5 筆資料就好
INSERT INTO tblIdentity (ExecuteTime) VALUES(GETDATE())
GO 5

-- 查詢目前資料
SELECT * FROM tblIdentity

使用 DBCC CheckIdent 會出現下述訊息


查詢 insert 10 筆資料,從 ExecuteTime 可以得知,DBCC CheckIdent 重置後的 ID 序號有從 0 開始跑



官方範例 - Reset the identity value on an empty table

[SQL] DELETE 和 TRUNCATE 內有紀錄使用 truncate 會重置 identity,Delete 本身沒有重置 identity 功能,但在官方範例 - Reset the identity value on an empty table 則是提出使用 Delete 刪除 Table 內全部資料後,可以透過 DBCC CheckIdent 來讓 identity 重置的做法,TSQL 示意
DELETE FROM TableName
GO
DBCC CHECKIDENT ('TableName', RESEED, 0);
GO

星期二, 8月 15, 2023

[SQL] 別名

在本機安裝 SQL Server 時,都習慣會 [自訂 instance name] 而不使用 [預設 instance name],使用 SSMS 連線時就必須使用 [.\自訂 InsanceName],想要使用 [.] 直接進行連線的話,必須依賴別名功能

When connecting to SQL Server running on the same computer as the client, you can use (local) as the server name. This is not encouraged as it leads to ambiguity, however it can be useful when the client is known to be running on the intended computer. For instance, when creating an application for mobile disconnected users, such as a sales force, where SQL Server will run on laptop computers and store project data, a client connecting to (local) would always connect to the SQL Server running on the laptop. The word localhost or a period (.) can be used in place of (local).
By default, SQL Server connects to a local instance of SQL Server using the Shared Memory protocol, and to an instance of SQL Server on another computer using either TCP/IP or Named Pipes. Create an alias when you are using TCP/IP or named pipes, and you want to provide a customized connection string, or when you want to use a name other than the server name for the connection.
別名是 SQL Native Client 功能,有區分 32 bit 和 64 bit,SSMS V19.1 是 32bit,所以只要設定 SQL Native Client 11.0 組態 (32 位元) 就行,設定路徑為 SQL Server 組態管理員 (Configuration Manager) => SQL Native Client 11.0 組態 (32 位元) => 別名

新增別名 => 輸入相關設定

星期四, 8月 10, 2023

[SSMS] 顯示行號

有行號標示情況下,在討論時有所幫助,印象中行號功能預設是啟用,但這次在新環境上安裝 SSMS V19.1 發現還是得手動去開啟


星期一, 8月 07, 2023

[C#] DataGridView 綁定自訂型別

社群內看到的問題,希望在 DataGridView 上可以直接綁定自定型別,自訂型別示意如下
public class Person
{
    public string Name { get; set; }

    public Address Address { get; set; }
}

public class Address
{
    public string City { get; set; }
}
重點放在 Addresss class 能否直接綁定在 DataGridView 上,透過 DataGridView.CellFormatting event 來做到,Code 如下
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DGVDataBinding
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private DataGridViewTextBoxColumn _colCity { get; set; }

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.AutoGenerateColumns = false;

            ColumnInit();
            
            SetDataSource();

            dataGridView1.CellFormatting += DataGridView1_CellFormatting;
        }

        private void ColumnInit()
        {
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn()
            {
                HeaderText = "姓名",
                DataPropertyName = nameof(Member.Name),
            });

            _colCity = new DataGridViewTextBoxColumn()
            {
                HeaderText = "都市",
                // 直接綁定 Address Class
                DataPropertyName = nameof(Address),
            };
            dataGridView1.Columns.Add(_colCity);
        }

        private void SetDataSource()
        {
            List<Member> source = new List<Member>();
            source.Add(new Member()
            {
                Name = "名字 1",
                Address = new Address() { City = "台北" }
            });
            source.Add(new Member()
            {
                Name = "名字 2",
                Address = new Address() { City = "高雄" }
            });

            dataGridView1.DataSource = source;
        }

        private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (e.ColumnIndex == _colCity.Index)
            {
                // DataPropertyName 設定為 Address,判斷是否可以轉為 Class
                // 可以轉為 class 後,把 City 欄位資料塞回去            
                if (e.Value is Address a)
                    e.Value = a.City;
            }
        }
    }

    public class Member
    {
        public string Name { get; set; }

        public Address Address { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
    }
}


另外有大神也分享在 RowAdded event 內顯示 Address 方式,雖然事件不同,但基本上原理都是相同的,把資料塞回去就是

星期五, 8月 04, 2023

[SQL] SQL Server 2022 上安裝 SQL Server Native Client

重新安裝 OS 後重建程式環境時發現,本機上安裝 SQL Server 2022 後,SQL Server Native Client 竟然是空的,沒有辦法建立別名來使用
 
SQL Server Native Client  內的 [用戶端通訊協定] 內理論上要有下述三個通訊協定
  • 共用記憶體
  • TCP/IP
  • 具名管道


新增名時,各選項都無法進行輸入,唯讀狀態的 fu


在官方文件 - Installing SQL Server Native Client 上有說明,SQL Server 2022 已經移除 SQL Server Native Client 囉


官方文件內有提到安裝方式,我是從 SQL Serve 2019 ISO 檔案內搜尋找到安裝檔案 sqlncli.msi,直接執行進行安裝


執行 sqlncli.msi 後,接續就是 step by step 完成安裝囉