[C#] 利用 interface(介面) abstract(抽象) override(覆寫) inherit(繼承) 實作簡單範例

來源:

  1. (原創) interface和abstract class有何不同? (C/C++) (.NET) (C#)
  2. [C#] abstract 和 virtual 函數的差異

 

這篇真的寫得很棒,大家一定要點進去看看,並自己動手寫Code !!
而我自己寫一篇只是為了建檔,方便日後自己觀看用,裡面的Code都是基於上面教學文寫的,自己只是加了一個AutoDoor的功能而已。

 


 

  1. 建立一個abstract的Door類別,裡面有Open(開門)與Close(關門)這兩個虛擬方法可以用
    abstract class Door
    {
        public virtual void Open()
        {
            Console.WriteLine("Open Door");
        }
        public virtual void Close()
        {
            Console.WriteLine("Close Door");
        }
    }
    

     

  2. 建立一個HorizontalDoor類別,它繼承了原先的Door,所以它也有Open與Close這兩個方法可以用
    class HorizontalDoor : Door { }
    

     

  3. 建立一個VerticalDoor類別,它也繼承了Door,可是我在裡面override了原先的Open與Close,另外實作其方法
    class VerticalDoor : Door
    {
        public override void Open()
        {
            Console.WriteLine("Open vertically");
        }
        public override void Close()
        {
            Console.WriteLine("Close vertically");
        }
    }
    

     

  4. 建立一個IAlarm介面,裡面定義了Alert這個方法
    interface IAlarm
    {
        void Alert();
    }
    

     

  5. 建立一個Alarm類別,它繼承了IAlarm,並在裡面實作Alert
    class Alarm : IAlarm
    {
        public void Alert()
        {
            Console.WriteLine("Ring ~~");
        }
    }
    

     

  6. 建立一個AlarmDoor類別,它繼承了Door,同時在裡面使用了Alarm類別的Alert方法
    class AlarmDoor : Door
    {
        private IAlarm _alarm;
    
        public AlarmDoor()
        {
            _alarm = new Alarm();
        }
    
        public void Alert()
        {
            _alarm.Alert();
        }
    }
    

     

  7. 建立一個AutoAlarmDoor類別,它繼承了AlarmDoor,並覆寫了原本的Open方法,裡面呼叫base.Open方法並接著呼叫Alert方法
    class AutoAlarmDoor : AlarmDoor
    {
        public override void Open()
        {
            base.Open();
            Alert();
        }
    }
    

     

  8. 建立一個DoorController類別,這個類別是用來控制管理所有的Door
    class DoorController
    {
        protected List<Door> _dootList = new List<Door>();
    
        public void AddDoor(Door Door)
        {
            _dootList.Add(Door);
        }
    
        public void OpenDoor()
        {
            foreach (var item in _dootList)
            {
                item.Open();
            }
        }
    }
    

     

  9. 完成 !!
    static void Main(string[] args)
    {
        DoorController dc = new DoorController();
        dc.AddDoor(new HorizontalDoor());
        dc.AddDoor(new VerticalDoor());
        dc.AddDoor(new AlarmDoor());
        dc.AddDoor(new AutoAlarmDoor());
    
        dc.OpenDoor();
    
        Console.ReadLine();
    }

     

  10. 執行結果
    2016-09-07 23_06_31-file____C__Users_Minsheng_Desktop_ConsoleApplication_Door_ConsoleApplication_Doo

 

  • 注意事項
    1. abstract method 不會有程式內容
    2. abstract method 繼承後,一定要 override
    3. virtual method 一定要有程式內容
    4. 宣告為 virtual 的 method,繼承後才可以進行 override
    5. 設定為 virtual 的 method,沒有一定要 override

 

       

[MSSQL] 使用 T-SQL 實作分頁

很多表格會遇上資料有上萬筆資料或者上千萬時的大數據,這時如果還是把所有資料撈出來在分頁的話,會造成使用者頁面讀取時間過久,更會有伺服器壓力倍增的問題,這裡提供一個SQL解決方案。

SQL如下:

DECLARE @PageNum AS BIGINT;
DECLARE @PageSize AS BIGINT;
DECLARE @PageCount AS BIGINT;
SET @PageNum = 3;
SET @PageSize = 10;
SET @PageCount = (	SELECT	COUNT(1)
					FROM	dbo.TBase_Product
					WHERE	Product_State != 9) / @PageSize;

IF @PageNum < 1	SET @PageNum = 1;

WITH Temp AS
(
	SELECT	*,
			ROW_NUMBER() OVER(ORDER BY Product_ID) AS RowNum
	FROM dbo.TBase_Product
)

SELECT	RowNum, @PageCount AS PageCount
FROM	Temp
WHERE	RowNum 
		BETWEEN ((@PageNum - 1) * @PageSize + 1) 
			AND (@PageNum * @PageSize)
ORDER BY Product_ID;

執行結果:

2016-09-03 01_01_10-SQLQuery9.sql - exfast.me,6000.iPCE_Coding (shuangrain (143))_ - Microsoft SQL S

 

 

參考:

  1. How to return a page of results from SQL?
  2. Select Count(*) / Count(1) / Count(欄位名) 的差異
       

[C#] 複製 Model 後異動時會互相引響

有一需求必須複製一個Model,這時如果異動Model_Copy時會造成Model_Source也跟著被更動,爬文後找到了一些方法來測試,問題依然存在…

 

  1. 用等於(=)的方式取值
    • 程式碼
      2016-08-25 22_03_12-ConsoleApplication1 - Microsoft Visual Studio
    • 結果:
      2016-08-25 22_03_39-file____C__Users_Minsheng_Desktop_ConsoleApplication1_ConsoleApplication1_bin_De
  2. 用new建立新的物件的方式取值
    • 程式碼
      2016-08-25 22_06_46-ConsoleApplication1 [執行] - Microsoft Visual Studio
    • 結果
      2016-08-25 22_03_39-file____C__Users_Minsheng_Desktop_ConsoleApplication1_ConsoleApplication1_bin_De
  3. 利用LINQ的方式取值
    • 程式碼
      2016-08-25 22_08_09-ConsoleApplication1 [執行] - Microsoft Visual Studio
    • 結果
      2016-08-25 22_03_39-file____C__Users_Minsheng_Desktop_ConsoleApplication1_ConsoleApplication1_bin_De

 

最後終於找到了一個方法可以用,那就是讓Model繼承ICloneable並使用Object中的MemberwiseClone()來實作Clone(),就可以順利Copy啦!

  • 程式碼
    1. Model
      2016-08-25 22_11_30-ConsoleApplication1 [執行] - Microsoft Visual Studio
    2. 利用LINQ來呼叫Clone()方法
      2016-08-25 22_46_21-ConsoleApplication1 - Microsoft Visual Studio
  • 結果
    2016-08-25 22_15_03-file____C__Users_Minsheng_Desktop_ConsoleApplication1_ConsoleApplication1_bin_De

 

       

[MSSQL] SQL Server Management Studio 連線非預設 1433 port 埠號

參考:SQL Server 透過 TCP/IP 遠端連線時如何使用非 1433 埠號

 

未命名

自從把SQL Server放到公用網路上的時候,就常常被人暴力破解Try我的密碼,雖然不至於被猜到,但是看了總是不太開心,於是乎就把預設的Port修改掉了,卻發生使用SQL Server Management Studio無法連線的問題,之前用MySQL時格式不外乎就是在後面加上:port但轉來MSSQL卻發生無法連線的問題…

 

爬了一下文才發現,使用ip,port(127.0.0.1,4321)這種格式就可以正常連線囉!
2016-08-20 18_18_00-連接到伺服器

       

[MSSQL] SQL Server Management Studio 連線工具

來源:使用 SQL Server Management Studio 連接到 SQL Database 並執行範例 T-SQL 查詢

 

SQL Server Management Studio (SSMS) 是一個整合式環境,您可以加以利用來存取、設定、管理及開發 SQL Server 的所有元件。 SSMS 利用許多豐富的指令碼編輯器來合併一群非常廣泛的圖形工具,使所有技術層級的開發人員及管理員都能夠存取。 此版除了提升與舊版 SQL Server 之間的相容性之外,也改進了獨立 Web 安裝程式,以及 SSMS 中,當有新版本可用時的快顯通知。

 

下載 SQL Server Management Studio (SSMS)

 

筆記一下…

2016-07-31 02_52_18-Microsoft SQL Server Management Studio

       

[C#] 使用 AutoMapper 快速轉換有相同資料的 Model

因為工作因素發生了需要將兩個具有相同資料的Model進行轉換,但是如果手動轉換的話太累了,工程師就是懶嘛~
於是乎就拜了Google大神找到了一個名叫AutoMapper套件。

 

  1. 從NuGet下載AutoMapper
    01
  2. 新增兩組相同的Model
    class Model_1
    {
    	public string Name { get; set; }
    
    	public int Year { get; set; }
    
    	public DateTime Date { get; set; }
    }
    
    class Model_2
    {
    	public string Name { get; set; }
    
    	public int Year { get; set; }
    
    	public DateTime Date { get; set; }
    }
    
  3. 轉換用的方法
    static TModel_2 ConvertModelToModel<TModel_1, TModel_2>(TModel_1 list)
    {
    	Mapper.Initialize(cfg =>
    	{
    		cfg.CreateMissingTypeMaps = true;
    		cfg.CreateMap<TModel_1, TModel_2>().ReverseMap();
    	});
    	Mapper.Configuration.AssertConfigurationIsValid();
    
    	var converted = Mapper.Map<TModel_2>(list);
    	return converted;
    }
  4. 轉換
    static void Main(string[] args)
    {
    	Model_1 model1 = new Model_1();
    	Model_2 model2 = new Model_2();
    
    
    	model1.Name = "王小明";
    	model1.Year = 2016;
    	model1.Date = DateTime.UtcNow.AddHours(8);
    
    
    	Console.WriteLine("=== 轉換前 ===");
    	Console.WriteLine("model1=name:{0}, year:{1}, date:{2}, type:{3}", model1.Name, model1.Year, model1.Date, model1.GetType());
    	Console.WriteLine("model2=name:{0}, year:{1}, date:{2}, type:{3}", model2.Name, model2.Year, model2.Date, model2.GetType());
    
    	model2 = ConvertModelToModel<Model_1, Model_2>(model1);
    
    	Console.WriteLine("=== 轉換後 ===");
    	Console.WriteLine("model1=name:{0}, year:{1}, date:{2}, type:{3}", model1.Name, model1.Year, model1.Date, model1.GetType());
    	Console.WriteLine("model2=name:{0}, year:{1}, date:{2}, type:{3}", model2.Name, model2.Year, model2.Date, model2.GetType());
    
    	Console.ReadLine();
    }
  5. 結果
    02

 

原始碼:https://github.com/shuangrain/ConsoleApplication_AutoMapper

       

[C#][ASP.NET MVC5] 繼承 AuthorizeAttribute 來實作自訂驗證

有時候會需要頁面會需要依照使用者權限的不同,可以進入的頁面也不同,在MVC裡面有預設Role與User的方式來篩選使用者,不過有時候權限分細一點時就沒辦法應付了,這個時候就需要自訂驗證了。

 

權限表單的結構資料如下:

01

  1. 先在登入成功的地方放入一段程式,來把使用者有權限進入的頁面以字串的方式存入Session
    using (var db = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
    
    {
    	String account = HttpContext.User.Identity.Name.ToString();
    	var list = db.Query<int>(@"
    SELECT 
    [a].[List_Id]
    FROM [dbo].[Permissions] AS [a]
    WHERE [a].[User_Id] = 
    (	SELECT [Id]
    FROm [dbo].[AspNetUsers] AS [z]
    WHERE [z].Email = @Email)", new { Email = model.Email }).ToList<int>();
    
    	Session["Permissions"] = string.Join(",", list.ToArray());
    }

     

  2. 再來新建一個檔案名為CustomAuthorize.cs,程式碼如下:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace WebApplication_CustomVerification.Verification
    {
        public class CustomAuthorize : AuthorizeAttribute
        {
            public int ListId { get; set; }
    
            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                if (httpContext == null)
                {
                    throw new ArgumentNullException("httpContext");
                }
    
                //判斷是否已驗證
                if (httpContext.User.Identity.IsAuthenticated == false)
                {
                    return false;
                }
    
                bool boolIsRight = false;
    
                //Session過期,要求重新登入
                HttpSessionStateBase session = httpContext.Session;
                if (session.Count != 0 &&
                    session["Permissions"] != null &&
                    session["Permissions"].ToString() != "")
                {
                    List<string> list = session["Permissions"].ToString().Split(',').ToList();
                    foreach (var item in list)
                    {
                        if (item == ListId.ToString())
                        {
                            boolIsRight = true;
                            break;
                        }
                    }
                }
    
                return boolIsRight;
            }
        }
    }

    這邊覆寫了原本驗證的機制,改成判斷先前存入Session內的字串。

  3. 這樣就可以在Action上面加上標籤來驗證使用者權限囉!
    using System.Web.Mvc;
    using WebApplication_CustomVerification.Verification;
    
    namespace WebApplication_CustomVerification.Controllers
    {
        public class HomeController : Controller
        {
    
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult About()
            {
                ViewBag.Message = "Your application description page.";
    
                return View();
            }
    
            public ActionResult Contact()
            {
                ViewBag.Message = "Your contact page.";
    
                return View();
            }
    
            [CustomAuthorize(ListId = 1111)]
            public ActionResult List_01()
            {
    
                return View();
            }
    
            [CustomAuthorize(ListId = 1112)]
            public ActionResult List_02()
            {
    
                return View();
            }
    
            [CustomAuthorize(ListId = 1113)]
            public ActionResult List_03()
            {
    
                return View();
            }
        }
    }

 

 

範例程式:https://github.com/shuangrain/WebApplication_CustomVerification

參考:[C#][ASP.NET MVC]自訂AuthorizeAttribute

       

[MySQL] INSERT資料前檢查資料是否重複

有時候需要檢查資料是否重複再填入,這裡簡單做個筆記。

程式碼

INSERT INTO `table` (`title`, `url`, `photocount`, `uploadtime`, `findtime`)
SELECT @title, @url, @photocount, @uploadtime, @findtime
FROM DUAL
WHERE NOT EXISTS (	SELECT 1
			FROM `table`
			WHERE `title` = @title
                    	AND `url` = @url);

 

SELECT @title, @url, @photocount, @uploadtime, @findtime

SELECT後面是準備填入的參數

WHERE NOT EXISTS (	SELECT 1
			FROM `table`
			WHERE `title` = @title
                    	AND `url` = @url);

WHERE這邊驗證資料是否重複

 

來源:MySQL INSERT 與 UPDATE 的一些特殊情況用法