\

Facebook


วันอังคารที่ 22 สิงหาคม พ.ศ. 2560

วิธีปลด Table Lock ใน SQL SERVER 2008R2


เคยเจอไหม เวลา SELECT ข้อมูลจาก database เเล้วมันหมุนไม่หยุด ไม่ใช้เพราะ query ทำงานนานเเต่อาจเป็นเพราะ table กำลังโดน lock กล่าวคือ process ก่อนหน้านั้นยังทำงานไม่เสร็จ ผู้ใช้คนอื่นจึงยังแตะต้อง ตารางนัน้ไม่ได้ แล้ววิธีปลด lock ต้องทำยังไงหล่ะ

กันก่อนแก้ 

ป้องกันการล็อกตารางในโดยใช้คำสั่ง WITH (NOLOCK) ถ้าใช้  SQL Server 2008R2 ก็ใช้คำสั่งสั้นๆ (NOLOCK) ตามหลังการ SELECT ยกตัวอย่างเช่น


SELECT TOP 100 * FROM dbo.product WITH (NOLOCK)


ถ้าล็อคไปแล้วแก้ไขโดย ค้นหาก่อนว่ามี PROCESS ไหนจองอยู่จากตาราง sys.dm_tran_locks เช่น


SELECT * FROM sys.dm_tran_locks

  WHERE resource_database_id = DB_ID()

  AND resource_associated_entity_id = OBJECT_ID(N'dbo.product');


ถ้ามี record เเสดงว่า process จอง Table อยู่ จัดการมันซะ มองหา process ID แล้วรันคำสั่ง


KILL {PROCESS_ID}

ลองซีเล็กอีกที พบว่าไม่เหลือเร็คคอดละ
จบงาน

[VS 2017] ReportViewer เทพออกรายงานตลอดกาลของ .Net


เวลาทำเว็บไปได้สักพักจนเริ่มมีคนใช้งานเยอะชึ้น user จะเริ่มถามหารายงาน สรุปยอด ผลงานเเต่ละวัน ซึ่งโจทย์ที่ได้มาจะเป็นแบบนี้ "ช่วยทำโมดูลรายงาน สรุปยอดให้หน่อย เอาที่สามารถค้นหาได้แล้วพิมพ์ออกมาเป็น Excel หรือไฟล์ PDF ได้ด้วยนะ" ครบเลย.. ถ้าเป็นเมื่อก่อนผมจะเขียนหน้า แสดงรายงานตามผลการค้นหา แล้วใช้ lib อีกตัวมาปั้นไฟล์ Excel อีกทีหนึ่ง

มันก็โอเคแต่เสียเวลาสัสๆ ทั้งเวลาเขียนโปรแกรม และเวลาตอนออกเอกสาร ดังนั้นเพื่อแก้ปัญหาเรื่องเวลา ถ้าใช้ .Net ผมอยากแนะนำให้รู้จัก ReportViewer แล้วชีวิตจะง่ายขึ้น

มันเป็นโมดูลหนึ่งของ Reporting Service ที่อยู่ใน .Net ตั้งเเต่ยุค Web Form จนมาถึงยุค MVC แล้วโมดูลนี้ก็ยังไม่ตาย มีคนเอามาประยุกใช้โดยเอา MVC ครอบ WebForm อีกทีหนึ่งเพื่อใช้งาน module ReportViwer ซึ่ง version ปัจจุบันที่ผมคือ 14.0 ซึ่งหน้าตามันจะดูขาวๆโมเดิลขึ้นมาหน่อย

ชอบตรงไหน 

ตรงที่โยน List, DataTable เข้าไปใน datasource ตารางก็โพล่แล้ว จัดว่าง่าย
ตรงที่มีปุ่ม download Excel หรือ PDF มาให้เลยไม่ต้องเขียนเพิ่ม

เกลียดมันที่ 

ต้องใช้ไฟล์ rdlc เป็น template เอกสาร แล้วไอ้ไฟล์นี้ต้องแก้ใน Visual Sutio ผ่าน Report Designer
ต้องมี Model มารองรับทุก DataSet ที่แสดงในรายงาน

เริ่มเลยขี้เกียจพิมพ์!! 

1 ไปที่โปรเจค์ MVC สร้าง Controller มาใหม่ สร้าง Action มาใหม่แล้วสร้าง View ว่างๆมา บลาๆๆ
2. สร้างโฟลเดอร์ใหม่ใต้โปรเจคชื่อ Report ข้างในนั้น Add New Item.. เลือก WebForm C# ตั้งชื่อว่า ViewReport.aspx
3. ไปที่ package management พิมพ์

Install-Package Microsoft.ReportingServices.ReportViewerControl.WebForms

หรือ NuGet :
"ReportViewerControl.WebForms"

4. ไปที่ไฟล์ ViewReport.aspx ใส่โค๊ดที่หัว


<%@ Register assembly="Microsoft.ReportViewer.WebForms, Version=14.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" namespace="Microsoft.Reporting.WebForms" tagprefix="rsweb" %>


5.ใส่ ScriptManagerControl
6. เพิ่มโมดูล ReportViewer


<rsweb:ReportViewer ID="ReportViewer1" runat="server" ProcessingMode="Remote">

<ServerReport ReportPath="" ReportServerUrl="" />

</rsweb:ReportViewer>


คราวนี้เราจะ design ไฟล์ template แล้วถ้าใช้  VS 2017 เหมือนผมให้ถามกูเกิ้ลว่า "Microsoft Rdlc Report Designer for Visual Studio" แล้ว download มา install

สร้าง RDLC กัน

1. Add new Item.. > ค้นหา Report เเล้วเลือก Report ตั้งชื่อไฟลล์ว่า reportTemplate.rdlc 
2. เพิ่ม Add New Item.. > Visual C# > Data > DataSet ตั้งชื่อ dsMapper.xsd แล้วสร้าง column ใหม่สองอันชื่อ firstname (string) , surname (string)
2. ดับเบิ้ลคลิกไฟล์ rdlc ใต้ folder DataSet กดสร้างไหม เลือก dsMapper มาเป็น DataSource
3. เเล้วเพิ่มตารางลงในเอกสร้าง insert > table ลากคอลัมจาก folder DataSet มาวาง จัดทรงให้สวย



แสดงรายงาน ก้อปโค๊ดข้างล่าง ไปไว้ใน ViewReport.aspx.cs


DataTable table = new DataTable();

            table.Columns.Add("FirstName", typeof(string));

            table.Columns.Add("SurName", typeof(string));



            // Here we add five DataRows.

            table.Rows.Add("ชิน", "ชยุต");

            table.Rows.Add("Chayut", "Chin");

            table.Rows.Add("Hydralazine", "Christoff");

            table.Rows.Add("Combivent", "Janet");

            table.Rows.Add("Dilantin", "Melanie");



            if (!IsPostBack)

            {

                string ReportFile = HttpContext.Current.Request.PhysicalApplicationPath

                + "Report\\reportTemplate.rdlc";

                ReportViewer1.LocalReport.ReportPath = ReportFile;

              



                var rp = new ReportParameter("rp_name", "หัวเรื่อง".ToString());

                ReportViewer1.LocalReport.SetParameters(new ReportParameter[] { rp });

              

                /// add more sheet

                ReportDataSource rds = new ReportDataSource("DataSet1", table);

                ReportViewer1.LocalReport.DataSources.Add(rds);

                ReportViewer1.LocalReport.Refresh();

            }


พอกด รันโปรเจค หน้ารายงานจะขึ้นละ


อยากให้ดู web.config ส่วนที่เพิ่มมาคือ


ทีนี้ถ้าอยากใช้ใน MVC ก็ครอบ ViewReport.aspx ด้วย iFrame ซะ จำไอ้ View ว่างๆข้อแรกได้ไหม ใส่โค๊ดข้างล่างนี้ลงไป เช่น


<iframe src="~/Report/ViewReport.aspx?@ViewBag.queryStr" width="100%" height="410px"></iframe>


จบงาน..

วันอังคารที่ 15 สิงหาคม พ.ศ. 2560

[ASP.NET] วิธีเข้ารหัส connectionStrings ในไฟล์ web.config ให้อ่านไม่ออก


ปกติหลังจากเราสร้างเว็บแอปเสร็จเรียบร้อยแล้ว เมื่อจะส่ง deploy สิ่งหนึ่งที่ควรระมัดระวังคือ username และ password ของ DB Account ใน connection string ที่อยู่ภายในไฟล์ web.config ที่โชว์ทั้งตัวเลขตัวอักษรอย่างไม่เกรงใจใคร เรียกได้ว่าเมื่อมีใครเข้ามาแอบเปิดไฟล์นี้ดูก็สามารถขโมยข้อมูลเหล่านี้ออกไปได้อย่างง่ายดาย วิธีป้องกันคือการเข้ารหัสมันซะ

สคลิปที่เราใช้มีชื่อว่า aspnet_regiis ซึ่งซ่อนตัวอยู่ภายในโฟล์เดอร์ของเฟรมเวิร์ค 4.0 ตามพาทนี้ C:\Windows\Microsoft.NET\Framework\v4.0.30319 ถ้าไม่เจอก็ให้ install .NET framwork 4 ก่อนครับ

ไปเพิ่ม path ใน environment ก่อน จะได้เรียกสคิปได้


เข้าไปที่ Control Panel > System and Security > System เลือก Advanced System settings แล้วเลือก Environment Variables มองหาพาแนล System variables แล้วแก้ไขค่า Path เพิ่ม C:\Windows\Microsoft.NET\Framework\v4.0.30319\ เข้าไป


หลังจากนั้นเปิด command line ขึ้นมาด้วย Administrator แล้วใส่คอมมานนี้ลงไปเพื่อเข้ารหัส section "connectionStrings" ที่อยู่ในไฟล์ web.config


aspnet_regiis -pef "connectionStrings" "D:\PathTo\File"


อย่าลืมเปลี่ยนพาท "D:\PathTo\File" ให้เป็นพาทจริงที่บรรจุไฟล์ .config


หลังจากนั้นถ้าขึ้นข้อความว่า Succeeded! แปลว่าเข้ารหัสสำเร็จ ทดลองเปิดไฟล์ดูจะพบว่าถูกเพิ่มส่วน EncryptedData เพื่อใส่ CipherData ขึ้นมาเป็นอันเสร็จสิ้น

ถ้าต้องการถอดรหัสคืน ทำไง?

อย่างง่าย แค่พิมพ์ command นี้ลงไป


aspnet_regiis -pef "connectionStrings" "D:\PathTo\File"


จบ

วันศุกร์ที่ 4 สิงหาคม พ.ศ. 2560

แก้ไข PDF ออนไลน์ไม่ต้องพึ่งโปรแกรมเสียเงิน



เป็นความอารมณ์เสียอย่างหนึ่งเมื่อต้องแก้งาน PDF แล้วเครื่องเราไม่มี software สำหรับแก้ ซึ่งตัวเสียเงินดีๆเห็นจะเป็น Acrobat Reader Pro แต่ตามสเตปโปรแกรมเมอร์ไส้แห้ง ใช้ของฟรีที่ดีต่อไป วันนี้จะมาแนะนำเว็บแก้ไขไฟล์พีดีเอฟออนไลน์แบบดีงามพระรามเก้า

Online PDF Editor ( BETA )

สามารถเข้าใช้งานได้ที่หน้าเว็บ https://www.sejda.com/pdf-editor


ถึงแม้จะเป็นเวอร์ชั่น ทดลอง แต่ฟีเจอร์สามารถใช้ได้เต็มๆ ไม่มีโฆษณากวนใจ และเครื่องมือหยิบจับใช้งานง่าย ด้วยรูปลักษณ์เว็บที่ดูสะอาดสะอ้านทำให้ หา tool ต่างๆได้ภายในไม่กี่วิ

ลงรายละเอียดเครื่องมือเเต่ละตัว

1. Text : ใส่อักษร
2. Link : ใส่ลิ้งสู่เว็บไซด์ เป็นกรอบเหลี่ยม คลุมส่วนที่จะคลิก อันนี้ผมบั๊ค มันไม่เป็นสี่เหลี่ยมปกติ
3. Forms : เพิ่มเครื่องหมาย ถูก ผิด จุด
4. Image : เพิ่มรูป
5. Sign : เพิ่มลายเซ็น ก็รูปอีกนั้นแหละ
6. Whiteout : ระบายขาวส่วนที่เลือก
7. Annotate : เพิ่มลักษณะอักษร เช่น ขีดกลาง
8. Shapes : เพิ่มรูปวงกลมหรือสี่เหลี่ยม แก้สีได้ด้วย เเต่มีสีให้เลือกจำกัด

ข้อดี 
1. ไม่ต้องลงโปรแกรมให้หนังเครื่อง
2. เครื่องมือเเก้เอกสาร 
3. คุณภาพไฟล์ไม่ถูกลดทอน

ข้อเสีย
1. ต้องต่ออินเตอร์เน็ตทุกครั้งเวลาใช้งาน
2. ใส่ annotation ไม่ได้
3. Object ที่ใส่จะกลายเป็นรูปลอยบนเอกสาร


เครื่องมือนี้ มีไว้ก็จบงานได้ ผมมักใช้ whiteout เพื่อระบายเก็บบางส่วนที่ไม่ต้องการแสดง จบเเล้วกด save เพื่อดาว์นโหลดไฟล์เอกสารได้เลย 

วันพุธที่ 2 สิงหาคม พ.ศ. 2560

4 วิธี รับค่าจาก Form ใน ASP.NET MVC แบบมือโปร



Form Post คือ โครตพื้นฐานการส่งข้อมูลบนเว็บไซด์แล้ว โดยฟอร์มจะทำหน้าที่สร้าง FormData ขึ้นมาเพื่อ POST กลับไปยัง SERVER

1. สร้างตัวแปรมารองรับใน controller : อันนี้คือวิธี basic ที่สุดโดยการตั้งชื่อตัวแปรให้ตรงกับชื่อ input การทำแบบนี้ถ้ามีการเปลี่ยน Model คุณก็ต้องมาเพิ่มหรือลด ตัวแปรใน controller เอง ไม่แนะนำ

ตัวอย่าง

[HttpPost]
public ViewResult Edit(string FirstName)
{
    ...
}


2.  สร้าง Interface / Class มารองรับ : ก็คือการสร้าง Model ขึ้นมา โดยตั้งชื่อตัวแปรให้ตรงกับชื่อ input แล้วโมเดลก็จะถูก Blinding อัตโนมัติ อันตรายของวิธีนี้คือ ถ้าคุณเล่นเอาโมเดลที่รับจากฟอร์ม โยนไป Database ตรงๆ โอกาสที่จะถูกอัพเดตผิดฟิลล์ก็เกิดขึ้น เช่น ในโมเดล มีฟิลล์ TotalAmount แต่ไม่มีการรับค่าจากฟอร์ม แฮกเกอร์ก็สามารถส่งค่าเข้ามาได้ หากเราข้ามการตรวจสอบไปก็อาจถูกอัพเดต TotalAmount ได้โดยที่ไม่รู้ตัว

ตัวอย่าง

[HttpPost]
public ViewResult Edit(User user)
{
    // ...
}

ฝั่ง View หน้าตาเป็นแบบนี้

@using (Html.BeginForm()) {
   
     @Html.EditorFor(model => model.FirstName)
     @Html.EditorFor(model => model.LastName)
        
    
}

สร้างโลเดลตามฟอร์ม

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int TotalAmount { get; set; }
}


ลองเอา Interface ไปรับค่าจากฟอร์มแทน แต่ตัว Class ให้สร้าง Property ที่มากกว่าก็สามารถแก้บัญหานี้ได้ระดับหนึ่ง


[HttpPost]
public ViewResult Edit(IUserInputModel user)
{
    // ...
}

อินเทอเฟสหน้าตาแบบนี้

public interface IUserInputModel
{
    string FirstName { get; set; }
    string LastName { get; set; }
}

ส่วนโมเดลจริง

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int TotalAmount { get; set; }
}

3. หรือตั้งค่า property ของ class เป็น ready only เพียงเท่านี้ ก็ไม่สามารถ set ค่าลง model class ได้ละ เเต่มันใช้ได้กับ MVC  4 , 5  ขึ้นไป


public class User 
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    [ReadOnly(true)]
    public int TotalAmount { get; set; }
}

4. ใช้ [Bind] attribute :  วิธีนี้เราสามารถเลือกเอาเฉพาะบางฟิลไปอัพเดตได้ หรือไม่เลือกบางฟิลล์ได้เช่นกัน เป็นวิธีที่เราจะเห็น จำนวนฟิลล์ชัดเจน

ตัวอย่าง แบบเลือกเอาเฉพาะฟิลล์

[HttpPost]
public ViewResult Edit([Bind(Include = "FirstName,LastName")] User user)
{
    // ...
}

แบบไม่เลือกบางฟิลล์

[HttpPost]
public ViewResult Edit([Bind(Exclude = "TotalAmount")] User user)
{
    // ...
}

เป็นอันเสร็จสิ้นครับ ที่มาของบทความ http://odetocode.com/blogs/scott/archive/2012/03/11/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx

วิธี HOST ไฟล์ JavaScript หรือ CSS ไว้บน DropBox แบบฟรีๆ


ผมเขียนบล็อกบน Blogger มีปัญหารที่เจอประจำคือ ไฟล์ JS หรือ CSS ที่ผมปรับแต่งเพิ่มเติมนั้น ไม่สามารถอัพโหลดขึ้นไปรวมกับทรีมได้ ผมต้องใส่ลิ้งจากเว็บนอกแทน ซึ่งมันกฌดีที่ไม่ต้องหนักโหลดที่หน้าเว็บเรา แต่ปัญหาคือเมื่อไหร่ที่เว็บนอกตัวนั้น down ไปเว็บเราที่มี dependency กับเค้าจะมีอาการโหลดไม่ขึ้น หรือเว็บช้าลากดิน งานนี้ต้องแก้

แล้วจะเอาไฟล์ไปฝากไว้ที่ไหนดีหล่ะ

โฮสของตัวเองก็ไม่มี ครั้นจะเอาไปวางบน Cloud Storage ก็เปลืองตังโดยใช้เหตุ เพราะคราวเล่นคิดระยะเวลาที่ request ไฟล์ด้วยในการคิดเงิน ผมเลยเลี่ยงมาใช้เว็บฝากไฟล์ฟรีแทน ซึ่งที่ดังเเล้วเป็นที่รู้จักตอนนี้ น่าจะเป็น DropBox

จัดไป DropBox !!

อัพโหลดไฟล์ขึ้นไปเลยครับ เเต่ขอเป็นใน Folder ว่างๆ เพราะเราจะทำเป็น Public Folder เพื่อให้สิทธิคนทั่วไปเข้าถึงได้

หลังจากนั้นคลิกขวาที่ไฟล์ เลือก "Shared" 

แล้วกด "Copy Link"

แล้วเปลี่ยน "www" ให้เป็น "dl" แทนอย่างเช่น

https://www.dropbox.com/s/w39yc90dtkxlq3o/csharp.js?dl=0
เปลี่ยนเป็น
https://dl.dropboxusercontent.com/s/w39yc90dtkxlq3o/csharp.js



เพียงเท่านี้ เราก็สามารถใช้ ไฟล์ได้อย่างสบายใจแล้ว โดยไม่มีติดขัด ถ้าเราไม่ทำ account ของ dropbox ถูกระงับซะก่อนนะ

ทดลองแก้ theme บน blogger

เอาลิ้งไปวางเลยครับ 

ไหนทดสอบสิ อันนี้ ผมทำ syntax highlighter  เอาไว้ซึ่งเรียก js ชื่อ rainbow จากดรอบบ็อก

namespace NerdDinner.Models
{
 using System.Data.Linq;
 using System.Data.Linq.Mapping;
 using System.Data;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Linq;
 using System.Linq.Expressions;
 using System.ComponentModel;
 using System;

 [System.Data.Linq.Mapping.DatabaseAttribute(Name="NerdDinner")]
 public partial class NerdDinnerDataContext : System.Data.Linq.DataContext
 {

  private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();

  public NerdDinnerDataContext() :
   base(global::System.Configuration.ConfigurationManager.ConnectionStrings["NerdDinnerConnectionString"].ConnectionString, mappingSource)
  {
   OnCreated();
  }

  public NerdDinnerDataContext(string connection) :
   base(connection, mappingSource)
  {
   OnCreated();
  }

  public NerdDinnerDataContext(System.Data.IDbConnection connection) :
   base(connection, mappingSource)
  {
   OnCreated();
  }

  public NerdDinnerDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
   base(connection, mappingSource)
  {
   OnCreated();
  }
       }
}

May be like this posts