星期五, 8月 29, 2014

[SQL] Schema

利用下述的範例來說明使用者預設 Schema 和撰寫 T-SQL 時,明確指定 Schema 的重要性

基礎建設
-- 在 Person 和 dbo 兩個 Schema 內,建立 SchemaDemo Table
-- HumanResources Schema 內,則是故意不建立 SchemaDemo Table
USE [AdventureWorks2012]
GO
 
IF OBJECT_ID('Person.SchemaDemo') IS NOT NULL
    DROP TABLE [Person].[SchemaDemo]
 
CREATE TABLE [Person].[SchemaDemo] (descript nchar(100))
INSERT INTO [Person].[SchemaDemo] (descript)
    VALUES(N'Schema 為 Person 的 SchemaDemo Table')
GO
 
IF OBJECT_ID('dbo.SchemaDemo') IS NOT NULL
    DROP TABLE [dbo].[SchemaDemo]
 
CREATE TABLE [dbo].[SchemaDemo] (descript nchar(100))
INSERT INTO [dbo].[SchemaDemo] (descript)
    VALUES(N'Schema 為 dbo 的 SchemaDemo Table')
GO
 
-- 建立測試 UserPerson 和 UserHumanResources,故意建立跟預設 Schema 同名的 User,方便辨識
USE [master]
GO
 
IF EXISTS (SELECT 1 FROM sys.sql_logins WHERE name = 'UserPerson')
    DROP LOGIN UserPerson
IF EXISTS (SELECT 1 FROM sys.sql_logins WHERE name = 'UserHumanResources')
    DROP LOGIN UserHumanResources
 
CREATE LOGIN [UserPerson]
    WITH PASSWORD = N'P@ssw0rd' , DEFAULT_DATABASE = [AdventureWorks2012]
 
CREATE LOGIN [UserHumanResources]
    WITH PASSWORD = N'P@ssw0rd' , DEFAULT_DATABASE = [AdventureWorks2012]
 
USE [AdventureWorks2012]
GO
 
IF EXISTS(SELECT 1 FROM sys.database_principals WHERE name = 'UserPerson')
    DROP USER UserPerson
 
CREATE USER [UserPerson] FOR LOGIN [UserPerson] WITH DEFAULT_SCHEMA = Person;
GO
 
IF EXISTS(SELECT 1 FROM sys.database_principals WHERE name = 'UserHumanResources')
    DROP USER UserHumanResources
 
CREATE USER [UserHumanResources] FOR LOGIN [UserHumanResources] WITH DEFAULT_SCHEMA = HumanResources;
GO
 
-- 授予存取 Table 權限
GRANT SELECT ON [Person].[SchemaDemo] TO [UserPerson]
GRANT SELECT ON [dbo].[SchemaDemo] TO [UserPerson]
GRANT SELECT ON [dbo].[SchemaDemo] TO [UserHumanResources]
GO
 
-- 確認使用者
SELECT
    Name,
    type_desc,
    default_database_name
FROM sys.sql_logins
WHERE name IN ('UserPerson','UserHumanResources')

-- 確認 User 的 預設 Schema
SELECT
    name,
    type_desc,
    default_schema_name
FROM sys.database_principals
WHERE default_schema_name IS NOT NULL
[SQL] Schema-1

星期四, 8月 28, 2014

[C#] 根據條件變化顏色

論壇問題
根據資料指定其背景顏色
  • 1 => 藍色
  • 2 => 紅色
  • 3 => 黃色
  • 4 => 綠色
using System.Data;
using System.Drawing;

namespace ConditionColor
{
    public partial class ConditionColor : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                DataTable dt = new DataTable("Demo");
                dt.Columns.Add("DataSeq", typeof(int));
                dt.Columns.Add("Kind", typeof(int));
                dt.Rows.Add(1, 4);
                dt.Rows.Add(2, 3);
                dt.Rows.Add(3, 1);
                dt.Rows.Add(4, 2);
                dt.Rows.Add(5, 3);
                dt.Rows.Add(6, 2);
                dt.Rows.Add(7, 1);
                dt.Rows.Add(8, 4);

                gvData.DataSource = dt;
                gvData.DataBind();
            }
        }
        // 在 RowDataBound 事件內設定顏色變化
        protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            // 判斷 RowType 是不是 DataRow
            if (e.Row.RowType != DataControlRowType.DataRow) return;
   
            // 抓出該資料並設定其背景顏色
            string kind = e.Row.Cells[1].Text;
            switch (kind)
            {
                case "1":
                     e.Row.Cells[1].BackColor = Color.Blue;
                     break;
                case "2":
                     e.Row.Cells[1].BackColor = Color.Red;
                     break;
                case "3":
                     e.Row.Cells[1].BackColor = Color.Yellow;
                     break;
                case "4":
                     e.Row.Cells[1].BackColor = Color.Green;
                     break;
                default:
                     break;
            }
        }
    }
}
[ASP.NET] 根據條件變化顏色

星期三, 8月 27, 2014

[C#] foreach 中的 index

MVA Twenty C# Questions Explained - [12 How do I get the index of the current iteration of a foreach loop?]

簡易範例:利用 for 迴圈取代 foreach
namespace MVATwentyQuestions
{
    class Program
    {
        static void Main(string[] args)
        {
            int curIndex = 0;
            // List
            List<string> stringList = new List<string>();
            stringList.Add("One");
            stringList.Add("Two");
            stringList.Add("Three");
            stringList.Add("Four");
            stringList.Add("Five");
            stringList.Add("Six");
            stringList.Add("Seven");

            for (int i = 0; i < stringList.Count; i++)
            {
                Console.WriteLine(i);
            }
        }
    }
}

星期二, 8月 26, 2014

[C#] 奇數列、偶數列背景顏色

不論任何語言,Grid 奇偶數列變色,好像是 Grid 變色的入門考題了,來練習一下
namespace OddEvenRowBG
{
    public partial class OddEvenRowBG : Form
    {
        public OddEvenRowBG()
        {
            InitializeComponent();
        }

        private void OddEvenRowBG_Load(object sender, EventArgs e)
        {
            // 建立 DataGridView 資料來源
            DataTable dt = new DataTable();

            dt.Columns.Add("ColEmpNO", typeof(int));
            dt.Columns.Add("ColEmpName", typeof(string));
            dt.Columns.Add("ColHireDate", typeof(DateTime));

            dt.Rows.Add(1, "趙一", new DateTime(1963, 7, 7));
            dt.Rows.Add(2, "洪二", new DateTime(1965, 5, 10));
            dt.Rows.Add(3, "張三", new DateTime(1981, 12, 11));
            dt.Rows.Add(4, "李四", new DateTime(1980, 1, 9));
            dt.Rows.Add(5, "王五", new DateTime(1973, 9, 9));

            if (dt.PrimaryKey.Length == 0) dt.Constraints.Add("PK", dt.Columns["colEmpNO"], true);
            dgvData.DataSource = dt;

            dgvData.AllowUserToAddRows = false;

            // 下列方法二擇一
            // 方法一:利用 DataGridView 本身屬性來完成
            dgvData.DefaultCellStyle.BackColor = Color.DarkGray;
            dgvData.AlternatingRowsDefaultCellStyle.BackColor = Color.DarkOliveGreen;

            // 方法二:自訂函數來完成
            OddEvenColor(dgvData);
        }

        public void OddEvenColor(DataGridView dgv)
        {
            if (dgv.Rows.Count == 0) return;
   
            // 下列方法二擇一
            // foreach 作法
            foreach (DataGridViewRow row in dgv.Rows)
            { 
                int index = dgv.Rows.IndexOf(row);
                if (index % 2 == 0)
                {
                    row.DefaultCellStyle.BackColor = Color.DarkGray;
                }
                else
                {
                    row.DefaultCellStyle.BackColor =  Color.DarkOliveGreen;
                }
            }

            // for 作法
            for (int i = 0; i < dgv.Rows.Count; i++)
            {
                if (i % 2 == 0)
                {
                    dgv.Rows[i].DefaultCellStyle.BackColor = Color.DarkGray;
                }
                else
                {
                    dgv.Rows[i].DefaultCellStyle.BackColor = Color.DarkOliveGreen;
                }
            }
        }
    }
}

星期一, 8月 25, 2014

[LINQ] SUM

網路問題
要利用 LINQ 找出整個 Table 的總合,延伸練習計算每個群組總合
using System.Data;

namespace LINQSum
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable("demo");
            dt.Columns.Add("Pro", typeof(string));
            dt.Columns.Add("cha", typeof(int));
            dt.Rows.Add("A", 12);
            dt.Rows.Add("B", 6);
            dt.Rows.Add("A", 14);
            dt.Rows.Add("C", 4);
            dt.Rows.Add("B", 8);

            Console.WriteLine("論壇問題:把 Table 內資料加總");

            var TotalSum = dt.AsEnumerable().Sum(datarow => datarow.Field<int>("cha"));

            Console.WriteLine("整個 Table 總合:{0}",TotalSum);

            Console.WriteLine("-------------------------------");

            Console.WriteLine("問題延伸:計算每個 Pro 群組總合");

            // Linq 寫法
            var query = from datarow in dt.AsEnumerable()
                        group datarow by datarow.Field<string>("Pro") into g
                        select new
                        {
                            Pro = g.Key,
                            TotalSum = g.Sum(r => r.Field<int>("cha"))
                        };

            // Lambda 寫法
            var query = dt.AsEnumerable().GroupBy(datarow => datarow.Field<string>("Pro")).Select(g => new { Pro = g.Key, TotalSum = g.Sum(r => r.Field<int>("cha")) });

            foreach (var item in query)
            {
                Console.WriteLine("{0}-{1}", item.Pro, item.TotalSum);
            }
        }
    }
}
[LINQ] SUM

星期三, 8月 20, 2014

[C#] IP address

MVA Twenty C# Questions Explained - [ 13 How do I get my own IP address in C#.]

MVA 範例
namespace MVATwentyQuestions
{
    class Program
    {
        static void Main(string[] args)
        {
            GetPrivateIP();
            string publicIP = GetPublicIP();
            Console.WriteLine("Public IP is: {0}", publicIP);
        }
    }

    static string GetPublicIP()
    {
        String address = "";
        WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
        using (WebResponse response = request.GetResponse())
        using (StreamReader stream = new StreamReader(response.GetResponseStream()))
        {
            address = stream.ReadToEnd();
        }

        //Search for the ip in the html
        int first = address.IndexOf("Address: ") + 9;
        int last = address.LastIndexOf("</body> ");
        address = address.Substring(first, last - first);

        return address;
    }

    static void GetPrivateIP()
    {
            
        foreach (var interfaces in NetworkInterface.GetAllNetworkInterfaces())
        {
            foreach (var address in interfaces.GetIPProperties().UnicastAddresses)
            {
                if (address.Address.AddressFamily == AddressFamily.InterNetwork)
                {
                    Console.WriteLine("IP Address:  " + address.Address.ToString());
                }
            }
        }
    }
}
搜尋網路文章來了解這個主題時,發現有 GetHostByName() 這個過時方法可以使用,但實際在 VS 上使用卻會出現提示
'System.Net.Dns.GetHostByName(string)' 已過時:GetHostByName is obsoleted for this typeof, please use GetHostEntry instead
[C#] IP address-1

星期二, 8月 19, 2014

[LINQ] 指定轉換無效

自我練習 LINQ 時,發生這個問題 - 指定轉換無效

[LINQ] 指定轉換無效-1

後來發現 SQL Server 內該欄位資料型態為 tinyint,其對應 .NET 資料型態為 byte,並不是 int,Orz ~~

    SQL Server ChildOrder 欄位資料型態
[LINQ] 指定轉換無效-2
    MSDN int 相關對應表
SQL Server.NET Framework
bigintInt64
intInt32
smallintInt16
tinyintByte

把 OrderBy 中 Field 資料型態改為 byte 就 pass
IEnumerable<datarow> demo = from dr in dt.AsEnumerable()
          where dr.Field<string>("ParentID").Trim() == "R"
          orderby dr.Field<byte>("ChildOrder")
          select dr;

星期一, 8月 18, 2014

[C#] DataGridView 的多選

論壇問題出處,把需求整理簡化為
DataGridView 多選,必須包含滑鼠單擊和滑鼠拖拉兩種選擇方式,該 Row 第一次被選擇背景顏色須改為灰色、該 Row 再次被選擇則變回白色
namespace MultiSelected
{
    public partial class MultiSelected : Form
    {
        public MultiSelected()
        {
            InitializeComponent();
        }

        private void MultiSelected_Load(object sender, EventArgs e)
        {
            // 建立 DataGridView 資料來源
            DataTable dt = new DataTable();

            dt.Columns.Add("ColEmpNO", typeof(int));
            dt.Columns.Add("ColEmpName", typeof(string));
            dt.Columns.Add("ColHireDate", typeof(DateTime));

            dt.Rows.Add(1, "趙一", new DateTime(1963, 7, 7));
            dt.Rows.Add(2, "洪二", new DateTime(1965, 5, 10));
            dt.Rows.Add(3, "張三", new DateTime(1981, 12, 11));
            dt.Rows.Add(4, "李四", new DateTime(1980, 1, 9));
            dt.Rows.Add(5, "王五", new DateTime(1973, 9, 9));

            if (dt.PrimaryKey.Length == 0) dt.Constraints.Add("PK", dt.Columns["colEmpNO"], true);
            dgvData.DataSource = dt;

            // DataGridView 設定
            // DataGridView.MultiSelect = true 才可以在 DataGridView 中全選,此為預設值
            dgvData.MultiSelect = true;
            // 設定 DataGridView 為全選整個 Row
            dgvData.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        }

        private void dgvData_MouseUp(object sender, MouseEventArgs e)
        {
            // 使用者選取的 row,透過 DataGridView.SelectedRows 找出
            foreach (DataGridViewRow row in dgvData.SelectedRows)
            {
                // 利用 條件式等於 true ? 結果1 : 結果2 來顯示 row 背景顏色
                row.DefaultCellStyle.BackColor = row.DefaultCellStyle.BackColor == Color.DarkGray ? Color.White : Color.DarkGray;
            }

            // 取消使用者選擇的 Row,這樣較容易觀察到 row 背景顏色變化,不會被 Highlight 遮住
            // 下面兩種語法都可以達到該目的
            dgvData.CurrentCell = null;
            //dgvData.ClearSelection();
        }
    }
}
[C#] DataGridView 的多選

建議利用 CheckBox 讓使用者點選,會是一個比較簡單的 solution

星期三, 8月 13, 2014

[C#] 計算年齡

Twenty C# Questions Explained -[14 How do I calculate someone’s age in C#?]
  • while 作法
這篇文章 [VFP] GOMONTH() 應用 改為 C# 來撰寫
static void Main(string[] args)
{

    DateTime dts = new DateTime(1981, 12, 11);
    DateTime dte = new DateTime(2014, 6, 27);

    int ageYear = 0 , ageMonth = 0 , ageDay = 0 , cumMonth = 0;
    // dtw 為跑 while 的起始值
    DateTime dtw = dts;

    while (dtw <= dte)
    {
        dtw = dtw.AddMonths(1);
        cumMonth++;
    }
    dtw = dtw.AddMonths(-1);

    ageYear = cumMonth / 12;
    ageMonth = cumMonth % 12;
    ageDay = Convert.ToInt16((dte - dtw).TotalDays);
   
    Console.WriteLine("{0} 年 {1} 月 {2} 日", ageYear, ageMonth, ageDay);
}
[C#] 計算年齡

星期二, 8月 12, 2014

[C#] ListBox 內新增 Item

論壇問題
TextBox 比對 ListBox,TextBox 字串去比對 ListBox 是否有這筆資料,如果沒有就加入到 ListBox 內
namespace ListBoxAdd
{
    public partial class ListBoxAdd : Form
    {
        public ListBoxAdd()
        {
            InitializeComponent();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            // 利用 indexof 來判斷使用者輸入是否存在於 ListBox 內
            string inputValue = txtInput.Text;
            if (lstResult.Items.IndexOf(inputValue) != -1) return;
            lstResult.Items.Add(inputValue);
            txtInput.Text = "";
        }
    }
}
[C#] ListBox 內新增 Item

星期一, 8月 11, 2014

[VS] 建立 Class Property

之前都傻傻地一個字一個字 key Class 的 Property,在影片教學中才發現原來有這麼便捷的功能

Class 中輸入 prop 就可以看見內鍵的程式碼片段

[VS] 建立 Class Property-1

按兩次 TAB 鍵就可以完成啦,從下圖可以看見 Property 產生後,回傳資料型態是反灰的,此時可以直接進行修改,再按兩次 Tab 鍵會便成 PropertyName 反灰,完成輸入 PropertyName 只要按下 Enter 就行

[VS] 建立 Class Property-2

星期三, 8月 06, 2014

[C#] Enum 的 String 值

MVA Twenty C# Questions Explained - [15 How do I get the String Value of an enum ?]

影片內用 Enum.GetName() 和 ToString() 兩種方法取出 Enum String 值

MVA 範例
class Program
{
    static void Main(string[] args)
    {
        // Enum.GetName()   
        AuthMethod auth = AuthMethod.FORMS;
        string str1 = Enum.GetName(typeof(AuthMethod), auth);
        Console.WriteLine(str1);
        
        // ToString()
        string str2 = AuthMethod.WINDOWSAUTHENTICATION.ToString();
        Console.WriteLine(str2);
    }

    public enum AuthMethod
    {
        FORMS = 1,
        WINDOWSAUTHENTICATION = 2,
        SINGLESIGNON = 3
    }
}
[C#] Enum 的 String 值-1

星期二, 8月 05, 2014

[C#] 物件初始化

完成這兩篇練習 [C#] 根據 CheckBox 來顯示 DataGridView 欄位 2[C#] 動態產生內含 6 個 CheckBox 的 Panel 後,都有一個感覺就是要 new class 並給定 property 值怎麼這麼麻煩。

最近閱讀 MVA C# Fundamentals for Absolute Beginners - 22 Working with Collections 章節時才發現,原來從 3.0 開始就有 "物件初始化" 功能可以便捷地 new class 並設定 property 值
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<demo> demoList1 = new List<demo>();

            // [C#] 根據 CheckBox 來顯示 DataGridView 欄位 2 作法
            // new class 出來後,針對 property 設定值
            demo test1 = new demo();
            test1.property1 = "1";
            test1.property2 = "1";
            demoList1.Add(test1);

            // [C#] 動態產生內含 6 個 CheckBox 的 Panel 作法
            // 建立一個符合 property 數量的建構子,new class 時一併把 property 值傳入 class 去進行設定
            demo test2 = new demo("2", "2");
            demoList1.Add(test2);

            // MVA C# Fundamentals for Absolute Beginners - 22 Working with Collections
            // 以下從影片中學習到的
            // 物件初始化設定:不用建立符合 property 數量的建構子
            demo test3 = new demo() { property1 = "3", property2 = "3" };
            demoList1.Add(test3);

            // 此 test4 範例,但 code 的目的只是為了把資料篩進 demoList 中,該 class 名稱並不重要,如同下段 code
            demoList1.Add(new demo() { property1 = "4", property2 = "4" });

            // 集合初始設定
            // 集合初始設定式是一系列以逗號分隔的物件初始設定式
            List<demo> demolist2 = new List<demo>()
            {
                new demo(){property1 = "5", property2 ="5"},
                new demo(){property1 = "6", property2 ="6"}
            };

            // 把兩個 List 內資料都顯示出來
            foreach (demo item in demoList1)
            {
                Console.WriteLine("{0}", item.property1);
            }

            foreach (demo item in demolist2)
            {
                Console.WriteLine("{0}", item.property1);
            }
        }

        class demo
        {
            public string property1 { get; set; }
            public string property2 { get; set; }

            // [C#] 動態產生內含 6 個 CheckBox 的 Panel 作法
            public demo(string _property1, string _property2)
            {
                this.property1 = _property1;
                this.property2 = _property2;
            }

            public demo() { }
        }
    }
}
[C#] 物件初始化

星期一, 8月 04, 2014

[VS] 尋找命名空間

開始學習 C# 時,對於甚麼功能在哪個 namespace 內不是很清楚時,都是直接 Google 來了解,但原來 VS 就有內建功能可以了解

沒有正確引用 namespace 都會出現的錯誤訊息 "是否移漏 using 指示詞或組件參考"

[VS] 尋找命名空間-1

把滑鼠放在 StreamReader 上,會出現選項可以幫助使用者了解該使用那個 namespace

[VS] 尋找命名空間-2

點選 using System.IO 會把 namespace 加上最上面(下圖上面紅框)
點選 System.IO.StreamReader 會在 StreamReader 前面加上 System.IO 字樣(下圖下面紅框)

[VS] 尋找命名空間-3