2017年9月30日 星期六

[SQL] Compare Operator - where "=" and "in"

    • Step 1. 查詢
select * from Production.Product where Name = 'Chainring'
select * from Production.Product where Name = 'Chainring' or Name = 'Reflector'
select * from Production.Product where Name in ('Chainring', 'Reflector')
    • Step 2. 查詢結果
      • 查詢 1:where 條件較少相對成本較低
      • 查詢 2:where 條件較多相對成本較高
      • 查詢 3:使用 "=" 與 "in" 成本是相同
    • Step 3. 工具提示查看 I/O 與 CPU 成本
      • 估計的 I/O 成本:I/O 活動的估計成本
      • 估計的 CPU 成本:CPU 活動的估計成本
      • 估計的運算成本:估計的 I/O 成本 + 估計的 CPU 成本
      • 估計的子樹成本:該作業與子樹中所有作業的 “估計的運算成本” 累加總和
    • Result:
      1. where 條件越多越複雜,查詢成本相對會越高
      2. 使用 "=" 與 "in" 成本是相同
  • REF:
    • SQL Server 效能調校

2017年9月29日 星期五

[MVC] WebAPI C.R.U.D

  • 此篇介紹如何使用 MVC API 進行 CRUD
    • INSERT (C):INSERT 是將資料插入到資料庫物件中的指令
    • SELECT (R) :SELECT是SQL資料操縱語言(DML)中用於查詢表格內欄位資料的指令
    • UPDATE (U):UPDATE 指令是依給定條件,將符合條件的資料表中的資料更新為新的數值
    • DELETE (D):DELETE 指令為自資料庫物件中刪除資料的指令
    • Step 1. 
    • Step 2. 在 App_Data 中創建資料庫 
    • Step 3. 並建立一個 UserInfo table

    • Step 3. 建立 User Controller API,選取讀取/寫入動作 Web API

        // GET: api/User
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET: api/User/5
        public string Get(int id)
        {
            return "value";
        }

        // POST: api/User
        public void Post([FromBody]string value)
        {
        }

        // PUT: api/User/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE: api/User/5
        public void Delete(int id)
        {
        }
    • Step 4. 使用 Dapper 建立  CRUD 

namespace MVCAPICRUD.Models
{
    public class UserInfo
    {
        public int? id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}


using Dapper;
using MVCAPICRUD.Models;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web.Http;

namespace MVCAPICRUD.Controllers
{
    public class UserController : ApiController
    {
        private string ConnectionString = @"Data Source=(LocalDB)\v11.0;AttachDbFilename=D:\Demo\MVCAPICRUD\MVCAPICRUD\App_Data\Database.mdf;Integrated Security=True";

        // GET: api/User
        public IEnumerable<UserInfo> Get()
        {
            List<UserInfo> lUSerInfo;

            using (SqlConnection con = new SqlConnection(ConnectionString))
            {
                lUSerInfo = con.Query<UserInfo>(
                   "Select * from UserInfo",
                   commandTimeout: 0).ToList();
            }

            return lUSerInfo;
        }

        // GET: api/User/5
        public UserInfo Get(int id)
        {
            UserInfo userInfo;

            using (SqlConnection con = new SqlConnection(ConnectionString))
            {
                DynamicParameters Param = new DynamicParameters();
                Param.Add("@id", id, dbType: DbType.Int32);

                userInfo = con.Query<UserInfo>(
                   "SELECT * FROM UserInfo WHERE id = @id",
                   Param,
                   commandTimeout: 0).FirstOrDefault();
            }

            return userInfo;
        }

        // POST: api/User
        public void Post([FromBody]UserInfo value)
        {
            int count = 0;

            using (SqlConnection con = new SqlConnection(ConnectionString))
            {
                count = con.Execute(
                   "INSERT INTO UserInfo VALUES (@Name, @Age)",
                   value);
            }
        }

        // PUT: api/User/5
        public void Put([FromBody]UserInfo value)
        {
            int count = 0;

            using (SqlConnection con = new SqlConnection(ConnectionString))
            {
                count = con.Execute(
                   "UPDATE UserInfo SET Name = @Name, Age = @Age Where id = @id",
                   value);
            }
        }

        // DELETE: api/User/5
        public void Delete(int id)
        {
            int count = 0;

            using (SqlConnection con = new SqlConnection(ConnectionString))
            {
                DynamicParameters Param = new DynamicParameters();
                Param.Add("@id", id, dbType: DbType.Int32);

                count = con.Execute(
                   "DELETE FROM UserInfo WHERE id = @id",
                   Param,
                   commandTimeout: 0);
            }
        }
    }
}
    • Step 5. 測試
      • INSERT (C):
      • SELECT (R)
      • UPDATE (U)
      • DELETE (D)

2017年9月28日 星期四

[C#] ?:, ??, ?.

    • C 語言就有提供此運算方法
if (test > 0) // 任何 Boolean 運算式
{
    // test 為 true 時,所傳回的運算式。 可為逗號運算子。
    return expression1
}
else 
{
    // test 為 false 時,所傳回的運算式。 可為逗號運算子。
    return expression2
}
    • 根據條件傳回兩個運算式的其中一個
test ? expression1 : expression2
    • ?: 運算子可當做 if...else 陳述式的簡短表示法
    • 在一些大型運算式中,若使用 if...else 陳述式會顯得很冗長,因此通常會只用此大型運算式其中一部分

    • C# 2.0 後的運算子
    • 如果運算元不是 null,則會傳回左方運算元,否則傳回右方運算元
int? test = null;

int n = test == null ? 0 : test;
    • 主要判別 test != null (null coalescing operator) 情況
int? test = null;

int n = test ?? test;
    • 另個特性是可直接串連,最後如果 ABCD 都 null 就傳 E
int n = A ?? B ?? C ?? D ?? E;

    • C# 6.0 後的運算子
    • 成員存取 (?.) 或對 (?[) 作業編製索引之前,可用來測試是否為 Null

// null if customers is null 
int? length = customers?.Length; 
// null if customers is null    
Customer first = customers?[0];  
// null if customers, the first customer, or Orders is null
int? count = customers?[0]?.Orders?.Count();  
    • 協助您撰寫較少的程式碼來處理 Null 檢查,特別是遞減至資料結構

  • REF:

2017年9月27日 星期三

[JavaScript] JavaScript Print - printThis.js

  • 現在網頁排版不在局限 Html 框架,許多人使用 Bootstrap 進行排版,但需要列印網頁頁面時,如使用 Bootstrap 排版頁面會跑版,無法列印使用者所看到的頁面
  • printThis.js :此套件在列印時可以套用 css 的樣版
    • Step 1: 建立一個空專案,並創建 Home page
    • Step 2: 安裝  Bootstrap 
    • Step 3. 撰寫一個框架
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <button type="button" class="btn btn-default" onclick="printtable('DemoPrint')">
        列印
    </button>
    <div id="DemoPrint">
        <div class="row">
            <div class="col-xs-4">.col-xs-14</div>
            <div class="col-xs-4">.col-xs-14</div>
            <div class="col-xs-4">.col-xs-14</div>
        </div>
        <div class="row">
            <div class="col-xs-4">.col-xs-24</div>
            <div class="col-xs-4">.col-xs-24</div>
            <div class="col-xs-4">.col-xs-24</div>
        </div>
        <div class="row">
            <div class="col-xs-4">.col-xs-34</div>
            <div class="col-xs-4">.col-xs-34</div>
            <div class="col-xs-4">.col-xs-34</div>
        </div>
    </div>

    <script src="~/Scripts/jquery-1.9.1.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    <script>
        function printtable(pID) {
            console.log(pID);
            newwin = window.open('');
            newwin.document.write(document.getElementById('' + pID + '').outerHTML);
            newwin.print();
            newwin.close();
        };
    </script>
</body>
</html>
    • Step 4. 列印結果
      • 並無套用 Bootstrap 排版
    • Step 5. 安裝 printThis
    • Step 6. 使用 printThis
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <button type="button" class="btn btn-default" id="printtable">
        列印
    </button>
    <div id="DemoPrint">
        <div class="row">
            <div class="col-xs-4">.col-xs-14</div>
            <div class="col-xs-4">.col-xs-14</div>
            <div class="col-xs-4">.col-xs-14</div>
        </div>
        <div class="row">
            <div class="col-xs-4">.col-xs-24</div>
            <div class="col-xs-4">.col-xs-24</div>
            <div class="col-xs-4">.col-xs-24</div>
        </div>
        <div class="row">
            <div class="col-xs-4">.col-xs-34</div>
            <div class="col-xs-4">.col-xs-34</div>
            <div class="col-xs-4">.col-xs-34</div>
        </div>
    </div>
    <script src="~/Scripts/jquery-3.2.1.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    <script src="~/Scripts/printThis.js"></script>
    <script>
        $(function () {
            $('#printtable').click(function () {
                $("#DemoPrint").printThis({
                    debug: false,               // show the iframe for debugging
                    importCSS: true,            // import page CSS
                    importStyle: false,         // import style tags
                    printContainer: true,       // grab outer container as well as the contents of the selector
                    //loadCSS: "style.css",     // path to additional css file - use an array [] for multiple
                    pageTitle: "",              // add title to print page
                    removeInline: false,        // remove all inline styles from print elements
                    printDelay: 333,            // variable print delay; depending on complexity a higher value may be necessary
                    header: null,               // prefix to html
                    footer: null,               // postfix to html
                    base: false,                // preserve the BASE tag, or accept a string for the URL
                    formValues: false,          // preserve input/form values
                    canvas: false,              // copy canvas elements (experimental)
                    doctypeString: "",          // enter a different doctype for older markup
                    removeScripts: false,       // remove script tags from print content
                    copyTagClasses: false       // copy classes from the html & body tag
                });
            });
        });
    </script>
</body>
</html>
    • Step 6. 列印結果

2017年9月26日 星期二

[MSSQL] ERROR MESSAGE 3154, 備份組包含現有的 'XXX' 資料庫以外的資料庫備份

  • 近期需要讓備份的資料庫 (bak) 進行還原的動作,但預到下列的情況
    • 或者
RESTORE DATABASE VIESHOW_PORTAL_M  
FROM DISK = 'D:\DBData\10.12 DB\VIESHOW_PORTAL_M_backup_2017_09_26_020001_7860989.bak'; 
    • Step 1. 查尋備份資料庫資訊
RESTORE FILELISTONLY 
FROM DISK = N'D:\DBData\10.12 DB\VIESHOW_PORTAL_M_backup_2017_09_26_020001_7860989.bak'
    • Step 2. 使用指令 
RESTORE DATABASE VIESHOW_PORTAL_T -- 指定還原資料庫名稱 db
FROM DISK = N'D:\DBData\10.12 DB\VIESHOW_PORTAL_M_backup_2017_09_26_020001_7860989.bak' -- 資料庫備份檔 .bak 路徑
WITH
File = 1 , 
RECOVERY , 
REPLACE ,
MOVE 'HR31_PORTAL_I' TO N'D:\DBData\VIESHOW_PORTAL_T.mdf', -- 設定 MSSQL 資料庫存放路徑 (mdf)
MOVE 'HR31_PORTAL_I_log' TO N'D:\DBData\VIESHOW_PORTAL_T_log.ldf', -- 設定 Log 存放路徑
STATS = 10

2017年9月25日 星期一

[MSSQL] Move Database Files

  • 這幾天進行 MSSQL 大量資料開發時,發現 C 槽的硬碟空間不夠,查明才發現 MSSQL  佔存資料的位置在 C槽底下,導致大量資料匯入使得硬碟空間不足,因此需更動儲存的位置
    • Step 1. "伺服器屬性""資料庫設定",進行修改儲存位置,未來創建的資料庫將會在此路徑中
    • Step 3. 佔停資料庫
USE master
GO
ALTER DATABASE ReportDB SET OFFLINE WITH ROLLBACK IMMEDIATE
GO
    • Step 2. 複製 mdf 與 ldf 至修改儲存位置
    • Step 3. 使用指令修改資料庫位置

USE master
GO
ALTER DATABASE ReportDB
MODIFY FILE 
( NAME = ReportDB, 
FILENAME = 'D:\DBData\ReportDB.mdf'); -- New file path

USE master
GO
ALTER DATABASE ReportDB 
MODIFY FILE 
( NAME = ReportDB_log, 
FILENAME = 'D:\DBData\ReportDB_log.ldf'); -- New file path
    • Step 4. 起動資料庫

USE master
GO
ALTER DATABASE ReportDB SET ONLINE;
    • Step 5. 如有"作業系統錯誤 5: "5(存取被拒。)"。 (Microsoft SQL Server, 錯誤: 5120)",需設定如下

2017年9月24日 星期日

[MVC] Routing Engine - WabAPI (4)

  • 先前介紹網頁的 Routing Engine,而在 WebAPI 的 Routing Engine 是獨立分開
    • Step 1. 創建空專案為 WebAPI 
    • Step 2. App_Start 中 WebApiConfig.cs 為 WebApi 的 Routing Engine
using System.Web.Http;

namespace MVCWebApi
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 設定和服務

            // Web API 路由
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    • Step 3. Global.asax 中也有註冊
using System.Web.Http;

namespace MVCWebApi
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    }
}
    • Step 4. 創建 API Controller
    • Step 5. 預設會幫你建立一組完整的 HTML API,而 Controller 繼承為 ApiController
using System.Collections.Generic;
using System.Web.Http;

namespace MVCWebApi.Controllers
{
    public class DemoController : ApiController
    {
        // GET: api/Demo
        public IEnumerable Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET: api/Demo/5
        public string Get(int id)
        {
            return "value";
        }

        // POST: api/Demo
        public void Post([FromBody]string value)
        {
        }

        // PUT: api/Demo/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE: api/Demo/5
        public void Delete(int id)
        {
        }
    }
}
    • Step 6. 測試,如有特殊的 Routing 一樣需在 WebApiConfig 中註冊

2017年9月23日 星期六

[MVC] Routing Engine - multiple parameters (3)

public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            // 忽略所有 *.axd 的網址路徑
            // 在預設 RegisterRoutes 方法中的 IgnoreRoute 用來定義 不要透過 Routing 處理的網址
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",                    // 路由名稱:唯一名稱對應唯一的 Route
                url: "{controller}/{action}/{id}",  // URL 及參數:通過簡單的模式,將 URL 解析具有意義的字段
                defaults: new                       // 參數預設值
                {
                    controller = "Home",            // 默認值:提供與對應字段的默認值
                    action = "Index",
                    id = UrlParameter.Optional
                    // constraints                  // 約束:一系列的約束應用到 URL 模式上
                                                    //       用來嚴格定義 URL 對應 Route
                } 
            );
        }
    }
    • Step 2. 創建 Controller 如下:
      • 預設 Routing Engine 只有 id = UrlParameter.Optional ,因此 Parameters 只有 1 個 id
      • 如果將 int? id 改為 int? other,Routing Engine 沒有註冊 other 的 Parameters ,因此不會動作
    public class UserController : Controller
    {
        public ActionResult UserName(int? id)
        {
            ViewBag.myid = id;
            return View();
        }
    }
    • Step 3. Routing Engine 中註冊新的 Routing
            routes.MapRoute(
                name: "MultiParam",                    // 路由名稱:唯一名稱對應唯一的 Route
                url: "{controller}/{action}/{age}/{area}",  // URL 及參數:通過簡單的模式,將 URL 解析具有意義的字段
                defaults: new                       // 參數預設值
                {
                    controller = "Home",            // 默認值:提供與對應字段的默認值
                    action = "Index",
                    age = UrlParameter.Optional,
                    area = UrlParameter.Optional
                    // constraints                  // 約束:一系列的約束應用到 URL 模式上
                    //       用來嚴格定義 URL 對應 Route
                }
            );
    •  Step 4. Controller 加入 UserInfo
      • 輸入下列網址都是可以接收到訊息
        public ActionResult UserInfo(int? age, string area)
        {
            ViewBag.myage = age;
            ViewBag.myarea = area;
            return View();
        }

2017年9月22日 星期五

[JavaScript] JavaScript Excel - TableExport.js

  • 前篇介紹 DataTables.js
    • 使用起來是非常完整的免費套件,呈現與匯出報表都沒有太多的問題
    • 但遇到 thead 中有多個表頭需匯出像 Excel 這類的樣式,就會發生問題
    • 如此篇所描述 Multiple thead 產出 Excel 的問題,回答也是很簡單,就是不支援 Multiple thead 匯出的方式
    • Step 1. 參照此教學文進行測試
    • Step 2. 匯出 Excel 結果,只會顯示最後一組 thead
  • TableExport:HTML Table 內容匯出成各種格式的檔案,且也是 jQuery Plug-in
    • Step 1. 網站中有介紹需要安裝那些套件與套件的功能,主要安裝的有 
      • John Resig - jQuery
      • tableexport
      • SheetJS - js-xlsx
      • Eli Grey - FileSaver.js
    • Step 2. 安裝 
    • Step 3. 將手動安裝的檔案加入專案中
    • Step 4. 加入相關程式,並設置一個按鍵

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
    <link href="~/Content/DataTables/css/jquery.dataTables.min.css" rel="stylesheet" />
    <link href="~/Content/DataTables/css/buttons.dataTables.min.css" rel="stylesheet" />
    <link href="~/Content/DataTables/css/fixedColumns.dataTables.min.css" rel="stylesheet" />
    <!--TableExport-->
    <link href="~/Scripts/TableExport/dist/css/tableexport.min.css" rel="stylesheet" />
</head>
<body>
    <div>
        <input type="button" id="BtnExportExcel" class="btn btn-default" value="Excel">
    </div>

    // Table Data ... 

    <script src="~/Scripts/jquery-3.2.1.min.js"></script>
    <script src="~/Scripts/DataTables/jquery.dataTables.min.js"></script>
    <script src="~/Scripts/DataTables/dataTables.fixedColumns.min.js"></script>
    <script src="~/Scripts/DataTables/dataTables.bootstrap.min.js"></script>
    <script src="~/Scripts/DataTables/dataTables.buttons.min.js"></script>
    <script src="~/Scripts/jszip.min.js"></script>
    <script src="~/Scripts/pdfmake/pdfmake.min.js"></script>
    <script src="~/Scripts/pdfmake/vfs_fonts.js"></script>
    <script src="~/Scripts/DataTables/buttons.html5.min.js"></script>
    <script src="~/Scripts/DataTables/buttons.print.min.js"></script>
    <!--TableExport-->
    <script src="~/Scripts/SheetJS/xlsx.core.min.js"></script>
    <script src="~/Scripts/FileSaver.min.js"></script>
    <script src="~/Scripts/TableExport/dist/js/tableexport.min.js"></script>
    <script>
        $(function () {
            $('#example').DataTable({
                columnDefs: [{
                    visible: false,
                    targets: -1
                }],
                //dom: 'Bfrtip',
                //buttons: [
                //    'excelHtml5', 'pdfHtml5', 'print'
                //],
                fixedHeader: true,
                scrollY: 300,
                scrollX: true,
                scrollCollapse: true,
                searching: false,
                paging: false,
                ordering: false,
                fixedColumns: {
                    leftColumns: 1,
                    rightColumns: 1
                }
                //info: false
            });

            $('#BtnExportExcel').click(function (e) {
                var ExportButtons = document.getElementById('example');

                var instance = new TableExport(ExportButtons, {
                    headers: true,                          
                    footers: false,                         
                    formats: ['xlsx'],                      
                    filename: 'DemoExcel',        
                    bootstrap: false,                       
                    exportButtons: false,                                   
                    ignoreRows: null,                       
                    ignoreCols: null,                       
                    trimWhitespace: true                    
                });

                //                                        "id" of selector, format
                var exportData = instance.getExportData()['example']['xlsx'];
                instance.export2file(exportData.data, exportData.mimeType, exportData.filename, exportData.fileExtension);
            });

        });
    </script>
</body>
</html>
    • Step 4. 匯出 Excel
      • 成功的可抓取 Multiple thead,但匯出的欄位不會跨欄