4/27/16

[C# .NET] Classes and Objects

Trong ngôn ngữ lập trình hướng đối tượng (OOP), class chính là một data-type định nghĩa các biến và phương thức cho khai báo một object. Hay nói cách khác, class định nghĩa data-type cho object, tuy nhiên class không phải là một object. Một object là một thực thể dựa trên class, hay còn gọi là một khởi tạo (instance) của một class.

Value Types

Trong ngôn ngữ C#, có 2 cách để lưu trữ dữ liệu là bằng ReferenceValue.
Một vài kiểu data-type như int, double được sử dụng để khai báo các biến, đó chính là value-type. Chúng được lưu trữ trong bộ nhớ (memory) có địa chỉ được gọi là Stack.

References Types

Kiểu reference dùng để lưu trữ các đối tượng (object). Khi bạn khởi tạo một đối tượng, dữ liệu của nó được lưu trữ trên bộ nhớ được gọi là Heap. Nhưng địa chỉ (address) dẫn đến nó được lưu ở Stack, nó chứa địa chỉ (memory address) đến đối tượng thực tế trên Heap. Đó là lý do gọi là reference-type...

  • Stack: sử dụng để cấp phát bộ nhớ tĩnh (static memory), bao gồm cho tất cả value-types của bạn.
  • Heap: sử dụng để cấp phát bộ nhớ động (dynamic memory), bao gồm các objects tùy chỉnh mà có thể cần thêm bộ nhớ trong quá tình hoạt động (runtime).

Tham khảo thêm:

Created: 37/04/2016
Read now

4/21/16

[C# .NET] Convert Between Hexadecimal, Decimal, Octal, Binary With C#

[C# .NET] Convert Between Hexadecimal, Decimal, Octal, Binary With C#

Để chuyển đổi qua lại giữa các hệ cơ số trong lập trình C# bạn có thể tham khảo các phương thức sau đây.

Bài liên quan
Hexadecimal, Decimal, Octal, Binary


1. Hex

a.) Decimal

//Hex to Dec
var hex = "7E0";
var dec = Convert.ToInt32(hex, 16); //2016
//Dec to Hex
var hex2 = dec.ToString("X"); //7E0

b.) Octal

//Hex to Octal
var hex = "7E0";
var dec = Convert.ToInt32(hex,16); //2016
var oct = Convert.ToString(dec,8); //3740
//Octal to Hex
var dec2 = Convert.ToInt32(oct, 8); //2016
var hex2 = dec2.ToString("X"); //7E0

c.) Bin

//Hex to Bin
var hex = "7E0";  
var dec = Convert.ToInt32(hex,16); //2016
var bin = Convert.ToString(dec,2); //0111 1110 0000
//Bin to Hex
var dec2 = Convert.ToInt32(bin, 2); //2016
var hex2 = dec2.ToString("X"); //7E0

2. Dec

a. Octal

//Dec to Octal
var dec = 2016;
var oct = Convert.ToString(dec,8); //3740
//Octal to Dec
var dec2 = Convert.ToInt32(oct, 8); //2016

b. Bin

//Dec to Bin
var dec = 2016;
var bin = Convert.ToString(dec,2); //0111 1110 0000
//Bin to Dec
var dec2 = Convert.ToInt32(bin, 2); //2016


3. Octal

//Oct to Bin
var oct = "3740";
var dec = Convert.ToInt32(oct,8); //2016
var bin = Convert.ToString(dec, 2); //0111 1110 0000
//Bin to Oct
var dec2 = Convert.ToInt32(bin, 2); //2016
var oct2= Convert.ToString(dec2, 8); //3740


Created: 21/04/2016
Read now

4/13/16

[UWP] Use Entity Framework 7 and SQLite in Windows Universal Apps

[UWP] Use Entity Framework 7 and SQLite in Windows Universal Apps

Entity Framework nay hỗ trợ nền tảng Universal Windows Platforms, tuy vẫn còn nhiều issues nhưng cơ bản mọi thứ hoạt động khá trơn tru. Bạn có thể làm quen trước  thông qua ví dụ trên trang giới thiệu về EF: efproject.net

Với EF bạn có thể làm việc với các Database Provinders sau:
  • Microsoft SQL Server
  • SQLite
  • Microsoft SQL Server Compact Edition
  • Npgsql (PostgreSQL)
  • IBM Data Servers
  • InMemory (for testing)

Bạn có thể theo dõi bài viết trên trang giới thiệu để thực hiện ví dụ mẫu, tuy nhiên dưới đây là một vài lưu ý để bạn không gặp phải khó khăn khi thực hiện nó.

- Có thể sử dụng SQLite để thực hiện demo thêm sửa xóa.

- Chỉ cần 2 Install-Package như trên trang chủ đã hướng dẫn
Install-Package EntityFramework.SQLite –Pre
Install-Package EntityFramework.Commands –Pre
- Bạn có thể kết nối tới database một trong các nhà cung cấp đã nói ở trên nếu bạn có server riêng. Nếu không bạn có thể dùng InMemory để test hoặc sử dụng SQLite, nó sẽ tạo dữ liệu cục bộ trên thiết bị của bạn.

- Để không bị lỗi không hay khi tạo ví dụ mẫu, bạn nên tạo mới một blank project để không thiếu các thư viện cần thiết

- Add đoạn mã sau vào file Properties/Default.rd.xaml để giả quyết một issue của EF, điều này sẽ sớm được giải quyết
<!-- Add your application specific runtime directives here. -->
<Type Name="System.Collections.ArrayList" Dynamic="Required All" />

- Lệnh Add-Migration bạn chỉ thực hiện lần đầu sau đó bạn có thể đặt đoạn mã dưới đây:
using (var db = new YourContext())
{
     db.Database.Migrate();
}
Trong file App.cs để EF tự động cập nhật các thay đổi, nếu không bạn tự Add-Migration khi model thay đổi.

- Bạn có thể delete tất cả Migrations để làm lại và uninstall app trên thiết bị của bạn

Created: 13/04/2016
Read now

4/3/16

[UWP] Draw a Circle Sector With Path

Hình tròn (Circle) có thể được tạo một cách dễ dàng bởi các control có sẵn trong Universal App. Dưới đây là liệt kê một vài control cơ bản mà bạn có thể sử dụng:

  • Ellipse với Width = Height
  • Rectangle với Width = Height, RadiuX = RadiusY= Width/2
  • Grid/Border với Width = Height, CornerRadius =  Width/2

Vậy để vẽ một Sector của hình tròn thì sao? Đừng lo lắng, bạn có thể sử dụng Path để vẽ chúng. Path thực chất chỉ chứa các dữ liệu... để tạo nên  một hình phức tạp, thuộc tính chứa dữ liệu đó là Data.

Tìm hiểu thêm:


Nếu bạn làm việc bằng công cụ thiết kế trực quan thì dữ liệu Data tự tạo ra gồm một chuỗi các ký tự, thoạt trông khá khó hiểu. Nhưng nó chỉ là tọa độ, độ dài của các point, line và đều bắt đầu với một ký tự đại diện để phân biệt.

Tìm hiểu thêm:


Trong một yêu cầu mới với nhiều thay đổi, ví dụ như tạo Sector của hình tròn với bán kính (Radius), góc (Degrees), vị trí (Start angle - End angle) tùy biến. Có lẽ sử dụng code-behind sẽ dễ dàng hơn.

Figure 1: I had drawn on Visio 2016

A. Input

Radius: Nhập vào độ dài bán kính.
Angle/Percent: Nhập vào góc hoặc phần trăm Sector muốn tạo.
Start Angle: Tọa độ bắt đầu của Sector. Mặc định thì tọa độ 0 như trên hình
End Angle: Không cần thiết, ta dựa vào angle/percent + start angle ta có thể biết end angle.

B. Request

CenterPoint: Tọa độ vị trí trung tâm của hình tròn, bạn chọn ở đâu thì hình tròn sẽ nằm ở đó.
Radius: Độ dài bán kính
StartPoint: Tọa độ điểm bắt đầu của Arc, ta có công thức
var startX= centerPoint.X + radius * Math.Cos(startAngle * Math.PI / 180);
var startY = centerPoint.Y + radius * Math.Sin(startAngle  * Math.PI / 180);
EndPoint: Tọa độ điểm cuối của Arc, ta có công thức
var endX= centerPoint.X + radius * Math.Cos(endAngle * Math.PI / 180);
var endY = centerPoint.Y + radius * Math.Sin(endAngle  * Math.PI / 180);
Size: Width/Height của Arc, ta dựa vào Radius, do đó ta có Size(Radius,Radius)
Chú ý: Nếu bạn thay thế Angle/Percent bằng Radian thì rút gọn Math.PI/180 bằng Math.PI

C. Implementation Method: C#

private PathGeometry CreateCircleSectorAtPoint(double center, double radius, double percent, double startAngle)
{
    //Request
    var centerPoint = new Point(center, center);
    var angle = 360 * (percent / 100);
    var endAngle = startAngle + angle;

    var startX = centerPoint.X + radius * Math.Cos(startAngle * Math.PI / 180);
    var startY = centerPoint.Y + radius * Math.Sin(startAngle * Math.PI / 180);

    var endX =  centerPoint.X + radius * Math.Cos(endAngle * Math.PI / 180);
    var endY =  centerPoint.Y + radius * Math.Sin(endAngle * Math.PI / 180);

    //Path Figure

    PathFigure pf = new PathFigure();
    pf.StartPoint = new Point(startX, startY);
    pf.IsClosed = true;
    pf.IsFilled = true;

    //ARC
    ArcSegment arc = new ArcSegment();
    arc.Point = new Point(endX, endY);
    arc.Size = new Size(radius, radius);
    arc.IsLargeArc = percent > 50 ? true : false;
    arc.SweepDirection = SweepDirection.Clockwise;

    // Line Segment
    LineSegment ls = new LineSegment();
    ls.Point = new Point(center, center);

    // Add child
    PathSegmentCollection psc = new PathSegmentCollection();
    psc.Add(arc);
    psc.Add(ls);

    pf.Segments = psc;
    PathFigureCollection pfc = new PathFigureCollection();
    pfc.Add(pf);

    PathGeometry pg = new PathGeometry();
    pg.Figures = pfc;

    //Return Data
    return pg;
}

D. Result

Figure 2: Demo Circle Sector On Visual Studio 2015 - UWA

Done :)

E. Read more

Figure 3: About Sigment and Sector
See calculate for Sigment
Warning:
The argument to Math.Sin(a) and Math.Cos(a) is in radians, not degrees. To convert, multiply by π/180:
var a = Math.Sin(27);
// Result: 0.956375928404503
var b = Math.Sin(27 * Math.PI / 180);
// Result: 0.453990499739547
Try it in Visual Studio and your calculator!

Created: 03/04/2016
Updated: 04/04/2016
Updated: 05/04/2016
Full Source code: DrawCircleSector
Read now

3/29/16

[C# .NET] Làm Việc Với Lệnh Nhảy - Jump Statements

Các lệnh Jump giúp bạn thoát khỏi vòng lặp hiện tại, phương thức, scope. Các lệnh jump trong C# bao gồm:

  • break
  • continue
  • goto
  • return
  • throw


a.) Break

- Được dùng trong tất cả loại vòng lặp, switch
- Khi được gọi, nó sẽ thoát hoàn toàn khỏi vòng lặp hoặc switch mà không quay lại.
- Chỉ thoát khỏi vòng lặp mà nó được gọi, sau đó tiếp tục các lệnh trong phương thức của bạn.

b.) Continue

- Được dùng trong tất cả vòng lặp
- Đi kèm với lệnh rẽ nhánh IF nếu TRUE thì Continue có hiệu lực và quay lại vòng lặp.

c.) Goto

- Nhảy đến Case khác trong Switch hoặc nhảy đến một Label
- Với break chỉ thoát được một scope vòng lặp, thì goto giúp bạn thoát nhiều vòng lặp lồng
=> Nếu value là 0 thì chỉ có case 0 được thực thi, ngược lại value là 1 thì cả hai case 0 và 1 được thực thi .


=> Nếu lệnh Goto được gọi thì nó sẽ nhảy thẳng tới nhãn mà bạn khai báo. Đây là cách thoát vòng lặp lồng hiệu quả.

d.) Return

- Trả về kết quả method, properties ngay lập tức
- Nếu phương thức yêu cầu trả về kiểu Int thì cú pháp: return 8;
- Nếu phương thức kiểu void thì cú pháp chỉ đơn giản: return;

e.) Throw

- Dùng để ném ra một ngoại lệ
- Có thể bỏ qua việc implement một phương thức được yêu cầu
- Thường dùng với try-catch



Created: 29/03/2016
Read now

[UWP] Take Screenshot With Custom Size and Share It

Để chụp ảnh màn hình, ta sử dụng RenderTargetBitmap để render bitmap. Bạn có thể gán cho Image Control để hiển thị hoặc lưu lại để chia sẻ lên Facebook (hiện tại bạn chỉ share được ảnh từ local, do vậy phải lưu ảnh xuống. Các trường hợp khác có thể stream trực tiếp), Twitter, Instagram, Mail, Onenote, hoặc các ứng dụng hỗ trợ nhận share source.

Đọc thêm:


Trước tiên, muốn lưu ảnh ta cần thêm Package.appxmanifest | Capabilities | Pictures Libary

a.) Phương thức quan trọng nhất là chụp màn hình, lưu ảnh, chia sẻ nó
private async Task<bool> GetShareContent(DataRequest request)
{
    //BEGIN
    bool succeeded = false;
    DataRequestDeferral deferral = request.GetDeferral();

    // 0. Cature Screen
    var bitmap = new RenderTargetBitmap();
    await bitmap.RenderAsync(MyBorder); //Your UIElement Here <================================

    // 1. Create folder and file 
    var folder = await KnownFolders.PicturesLibrary.CreateFolderAsync("MySample", CreationCollisionOption.OpenIfExists);
    StorageFile file = await folder.CreateFileAsync("ScreenShot.png", CreationCollisionOption.GenerateUniqueName);

    // 2. Get the pixels & Write the pixels to a InMemoryRandomAccessStream       
    var displayInformation = DisplayInformation.GetForCurrentView();
    IBuffer pixelBuffer = await bitmap.GetPixelsAsync();
    byte[] pixels = pixelBuffer.ToArray();
    using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);

        encoder.SetPixelData(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Ignore,
                (uint)bitmap.PixelWidth,
                (uint)bitmap.PixelHeight,
                displayInformation.LogicalDpi,
                displayInformation.LogicalDpi,
                pixelBuffer.ToArray());
        await encoder.FlushAsync();


        // 3. Share it for all 
        DataPackage requestData = request.Data;
        // It's recommended to use both SetBitmap and SetStorageItems for sharing a single image
        // since the target app may only support one or the other.
        List<IStorageItem> imageItems = new List<IStorageItem>();
        imageItems.Add(file);
        requestData.SetStorageItems(imageItems);
        //requestData.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));
        requestData.Properties.Description = "ShareContent for Windows #BravoHex";
        requestData.Properties.Title = "Wow, this my screenshot :-)";
        //requestData.Properties.ApplicationName = "DemoApp";
        //requestData.SetApplicationLink(new Uri("http://www.bravohex.com"));
    }

    //END
    deferral.Complete();
    return succeeded;
}


b.) Đây là phương thức sự kiện  Share Content. Nó được gọi khi đăng ký
- Bạn có thể thông báo lỗi qua đoạn mã sau:
e.Request.FailWithDisplayText("Show Error...!");
private async void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs e)
{
    // Call the scenario specific function to populate the datapackage with the data to be shared.
    if (await GetShareContent(e.Request))
    {
        // Out of the datapackage properties, the title is required. If the scenario completed successfully, we need
        // to make sure the title is valid since the sample scenario gets the title from the user.
        if (String.IsNullOrEmpty(e.Request.Data.Properties.Title))
        {
            e.Request.FailWithDisplayText("Error...!");
        }
    }
}

c.) Bạn phải đăng ký sự kiện Share Content trước khi thực hiện hoặc hủy
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Register the current page as a share source.
    this.dataTransferManager = DataTransferManager.GetForCurrentView();
    this.dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested);
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    // Unregister the current page as a share source.
    this.dataTransferManager.DataRequested -= new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested);
}

d.) Thực hiện Share Content
private void Button_Click(object sender, RoutedEventArgs e)
{
    DataTransferManager.ShowShareUI();
}


Đây là app demo:


Ta sẽ chỉ chụp Border ở giữa. Kết quả sau khi chụp và chia sẻ:




Craeted: 29/03/2016
Source code: TakenScreenShotAndShareContent
Read now

3/23/16

[C# .NET] Làm Việc Với Vòng Lặp - Iteration Statements

Iteration Statements: Các lệnh lặp khiến các lệnh nhúng bên trong chúng được thực hiện lặp một cơ số lần, tùy thuộc vào điều kiện chấm dứt vòng lặp. Các lệnh này được thực hiện theo thứ tự, trừ khi gặp một lệnh nhảy (Jump Statements: break, continue, goto, return, throw).

Bài viết liên quan:

Kiến thức liên quan:
Trước khi đi vào tìm hiểu các vòng lặp trên, ta ôn lại kỉ niệm với việc tăng, giảm một biến i nào đó (i là cái tên quen thuộc phải không). Với các liệt kê ngắn gọn dưới đây, bạn hãy test lại trong chương trình.
  • int i = 0; //Khai báo biến i kiểu int, giá trị ban đầu là 0
  • i=i+1; //i cộng thêm 1 
  • i+=1; //i cộng thêm 1
  • i++; //i cộng thêm 1, nhưng giá trị nhận được không thay đổi
  • i--; //i trừ đi 1, nhưng giá trị nhận được không thay đổi
  • ++i; //i cộng thêm 1, giá trị nhận được bằng i
  • --i; //i trừ đi i, giá trị nhận được bằng i
Ví dụ:
int i = 0;
Console.WriteLine("I: {0} and I++: {1}", i, i++); //I: 0 and I++: 0
Console.WriteLine("I: {0} and ++I: {1}", i, ++i); //I: 1 and ++I: 2
Console.WriteLine("I: {0} and I++: {1}", i, i++); //I: 2 and I++: 2
Console.WriteLine("I: {0} and I++: {1}", i, i++); //I: 3 and I++: 3
Console.WriteLine("I: {0} and ++I: {1}", i, ++i); //I: 4 and ++I: 5
Console.WriteLine("I: {0} and ++I: {1}", i, ++i); //I: 5 and ++I: 6
Nếu vẫn chưa đủ rõ ràng, bạn có thể xem ví dụ ngắn hơn:
int i = 0;
Console.WriteLine("i: {0}",i); // i: 0

var ra = ++i;
Console.WriteLine("ra: {0}", ra); // ra: 1
var rb = i++;
Console.WriteLine("rb: {0}", rb); // rb: 1

//Final 
Console.WriteLine("i: {0}", i); // i: 2
Khi ++i quá trình thực thi như sau:
  • i là biến khởi tạo với giá trị 0
  • Giá trị của i sẽ sao chép vào biến tạm t, có nghĩa t = i tức t = 0
  • t sẽ tăng lên 1 tạo ra một giá trị mới, có nghĩa t + 1, tức 0  + 1 = 1
  • Giá trị mới được gán cho i, có nghĩa i = 1
  • Kết quả trả về của toán tử này là giá trị mới là 1

Khi i++ quá trình thực thi như sau:
  • i là biến khởi tạo với giá trị 0
  • Giá trị của i sẽ sao chép vào biến tạm t, có nghĩa t = i tức t = 0
  • t sẽ tăng lên 1 tạo ra một giá trị mới, có nghĩa t + 1, tức 0  + 1 = 1
  • Giá trị mới được gán cho i, có nghĩa i = 1
  • Kết quả trả về của toán tử này là giá trị của biến tạm t là 0
Mấu chốt để thấy sự khác biệt giữa hai toán tử  ++i hay i++ là nó trả về một kết quả R, cho dù i đã tăng lên 1 nhưng R lại nhận kết quả khác. Bạn dễ gặp sai lầm phổ biến khi sử dụng trong vòng lặp chẳng hạn như while(i++ < 5) bạn thấy i++ nhưng thực chất R mới là kết quả làm việc với 5. OK

Các từ khóa dùng trong vòng lặp:
  • do
  • for
  • foreach
  • in
  • while

do-while

Important: Vòng lặp do-while luôn thực thi một lần trước khi kiểm tra while để tiếp tục hoặc không.
Figure 1: do-while loop
- Vòng lặp do-while, cho phép bạn thực hiện một cơ số vòng lặp cho đến khi nào biểu thức chỉ định không còn thỏa mãn (False) thì kết thúc. Biểu thức này nằm trong while(specified expression evaluates). Chú ý, nếu bạn gán while(true) hoặc không kiểm soát được biến phục vụ cho biểu thức thì vòng lặp này vô tận (infinite loop).
- Có thể dùng: break, return, goto, throw để thoát hoàn toàn khỏi vòng lặp.
- Dùng continue để nhảy tới while và tiếp tục vòng lặp, nếu biểu thức vẫn thỏa mãn (True).

while

Tất nhiên vòng lặp While sẽ kiểm tra điều kiện trước khi thực thi lệnh. Và dừng khi biểu thức là False, bạn cũng có thể sử dụng: break, goto, return, throw để thoát ngay tức thì. Ngoài ra, dùng continue để thoát vòng lặp hiện tại và nhảy tới vòng kế tiếp.
Figure 2: while loop

for

Dùng để duyệt một danh sách, với điều kiện bạn cần biết độ dài của nó. Hoặc đơn giản, bạn chỉ duyệt một số cố định
Figure 3: for loop

foreach-in

Dùng để duyệt một danh sách, theo thứ tự mà không cần thiết lập rườm rà.
Figure 4: foreach-in loop


Editing...
Created: 23/03/2016
Read now

3/12/16

Implementation for ADO.NET and Entity Framework

[Editorial Unfinished] 
Giả sử bạn đã có kinh nghiệm sử dụng 2 công nghệ truy xuất dữ liệu  ADO.NET và Entity framework, vậy loại nào tốt hơn?

Trước hết điểm qua một vài thông tin quan trọng:
  • Chúng đều là công nghệ làm việc xoay quanh nền tảng .NET do Microsoft cung cấp.  ADO.NET đã có từ lâu, và EF hay còn gọi là ADO.NET Entity Framework ra đời sau và đầy chức năng mạnh mẽ.
  • Cả hai đều làm việc với nhiều loại Cơ sở dữ liệu khác nhau, ở đây ta chỉ ví dụ với SQL Server.
  • ADO.NET được tích hợp sẵn trong .NET Framework, ngược lại EF được đưa lên Nuget.org, khi cần sử dụng EF bạn phải cài đặt package vào dự án của mình (tất nhiên là cần kết nối internet để cài đặt).
  • ADO.NET yêu cầu bạn gửi lệnh SQL Commands hoặc sử dụng Stored Procedure trên SQL Server  để truy vấn dữ liệu, và bạn cũng cần triển khai các hàm xử lý điều này một cách dài dòng. Trong khi đó EF không cần bạn phải thông thạo SQL Server, có sẵn công cụ cho bạn generate liên kết giữa database và chương trình của bạn, sau đó có thể sử dụng Linq để truy vấn dữ liệu.
  • Không xét tới tính bảo mật hay sự hỗ trợ ứng dụng doanh nghiệp vừa và lớn hay không, rõ ràng EF là công cụ tốt nhất hiện nay để truy xuất dữ liệu trong nền tảng .NET. EF cho phép tăng tốc thời gian phát triển, khả năng bảo trì mã tốt hơn, bởi vì làm việc với EF bạn sẽ không cần quan tâm quá nhiều đến những công việc khó khăn để truy xuất dữ liệu từ Cơ sở dữ liệu.
  • Ngoài ra với tương lai của công nghệ đám mây, EF sẽ đáp ứng tốt nhu cầu làm việc của bạn.

Để có một cái nhìn trực quan, ta đi xem một dự án mẫu. Sau đó bạn sẽ tự đưa ra cho mình quan điểm về câu hỏi đầu bài viết.
Trong ví dụ này, tôi cố gắng triển khai hết các cách sử dụng ADO.NET và EF.

A. ADO.NET

Có một vài lớp mà bạn cần nắm rõ thông tin cơ bản sau:
(Hai namespace cần dùng là System.Data.SqlClient, System.Data)
  • SqlConnection: Lớp này xử lý việc đóng mở kết nối đến database.
  • SqlCommand: Lớp này giúp bạn gửi lệnh SQL hoặc tên của Procedure cùng tham số nếu cần. Bạn phải sử dụng phương thức phù hợp để gửi lệnh đi, tương đương với kết quả trả về là một table, một column hay là một số kiểu Int ghi nhận số rows được thực thi do lệnh Insert, Update, Delete chẳng hạn.
  • SqlDataReader: Duyệt kết quả theo từng dòng từ kết quả SqlCommand trả về. Giờ bạn cần duyệt để lấy kết quả cuối cùng ra.
  • SqlDataAdapter: Về kĩ thuật thì nó cũng phải sử dụng SqlCommand để gửi lệnh, nhưng giờ SqlCommand là một thuộc tính của SqlDataAdapter. Sau cùng bạn đổ kết quả từ SqlDataAdapter lên DataSet hoặc Table, hoặc duyệt sang danh sách tùy bạn.
  • DataSet: Dùng để lưu trữ dữ liệu của các Table như một bộ nhớ cache. Bạn có thể lưu xuống XML (hoặc dạng khác mà bạn biết) như là một database local nếu thấy cần thiết!

Ví dụ sẽ có 2 table dữ liệu như sau:
CREATE TABLE Department (
    Did  INT PRIMARY KEY NOT NULL,
    Name NVARCHAR (50) NULL
);

CREATE TABLE Employee (
    Id INT IDENTITY (1,1) NOT NULL,
    FullName NVARCHAR (50) NULL,
    [Address]  NVARCHAR (50) NULL,
    Did      INT FOREIGN KEY (Did) REFERENCES Department NULL
);

Và tốt hơn là ta nên tạo Store Procedure, thay vì truyền lệnh trực tiếp qua SqlCommand ta truyền tên của SP:
--Department
GO
CREATE PROCEDURE spDepartment_GetAll
AS
BEGIN
 SELECT Did, Name FROM Department 
END

GO
CREATE  PROCEDURE spDepartment_Insert
 @Name Nvarchar(50)=NULL
AS
BEGIN
 INSERT INTO Department(Name) VALUES(@Name)
END

GO
CREATE  PROCEDURE spDepartment_Update
 @Did Int,
 @Name Nvarchar(50)=NULL
AS
BEGIN
 UPDATE Department 
 SET Name=@Name
 WHERE Did= @Did
END

GO
CREATE  PROCEDURE spDepartment_Delete
 @Did Int
AS
BEGIN
 DELETE Department WHERE Did=@Did
END

--Employee
GO
CREATE PROCEDURE spEmployee_GetAll
 
AS
BEGIN
 SELECT Id, FullName, [Address],Did FROM Employee
END

GO
CREATE  PROCEDURE spEmployee_Insert
 @FullName Nvarchar(50),
 @Address Nvarchar(50)= NULL,
 @Did int
AS
BEGIN
 INSERT INTO Employee(FullName,[Address],Did) VALUES(@FullName,@Address,@Did) 
END

GO
CREATE  PROCEDURE spEmployee_Update
 @Id Int,
 @FullName Nvarchar(50)=NULL,
 @Address Nvarchar(50)= NULL,
 @Did int
AS
BEGIN
 UPDATE Employee 
 SET FullName=@FullName, [Address]=@Address,Did=@Did
 WHERE Id= @Id
END

GO
CREATE  PROCEDURE spEmployee_Delete
 @Id int
AS
BEGIN
 DELETE Employee 
 WHERE Id=@Id
END
--/


Figure 1: Hướng truy cập dữ liệu theo hai mô hình kết nối (phải) và phi kết nối (trái). 

Một điều quan trọng, bạn cần linh động chú ý cách sử dụng các classes, constructors, methods... có nhiều cách gõ code để khai báo một lệnh nhưng chúng đều đúng. Vì đơn giản mỗi lần .NET nâng cấp thì bổ sung nhiều chức năng mới, đồng thời vẫn giữ các chức năng cũ
Và nếu bạn làm việc với Thread bất đồng bộ, thì việc debug sẽ khó khăn nếu code gặp vấn đề. Chưa quen có thể dùng các phương thức thường để debug dễ hơn

1. Sử Dụng Mô Hình Kết Nối (Connected)

(Video: Đang cập nhật... & Mã nguồn: Sẽ cập nhật cuối bài viết này...)
Says: Cách này trông có vẻ đơn giản hơn mô hình phi kết nối, nhưng có vài điểm bạn có thể cần biết. Dùng mã dưới đây để đồng bộ dữ liệu khi select row trên DataGridView và Controls. Ví dụ:

private void BindingData()
{
    TxtName.DataBindings.Add("Text", datasourceName, "NameColumns", false, DataSourceUpdateMode.Never);
}

Để dễ dàng ta chọn DataTable đổ dữ liệu lên DataGridView. Tiếp tục nào...

Step by Step:
  • Khai báo 1 SqlConnection, xây dựng hàm đóng, mở kết nối.
  • Khai báo SqlCommand để gửi lệnh
  • Sử dụng SqlDataReader để đọc dữ liệu từ SqlCommand
  • Sử dụng Table, List hay bất cứ gì để lấy dữ liệu cuối cùng từ SqlDataReader
Các lớp cơ sở và giao diện xây dựng như sau:
  • Create database với 2 table như trên, và các store procedure đi kèm. Chỉ việc copy query và RUN
  • DAL: DataAccess.cs xây dựng các hàm kết nối, lấy dữ liệu, insert, update, delete. Bạn luôn phải mở kết nối, và có thể đóng lại sau khi đã lấy dữ liệu để giải phóng tài nguyên.
  • BLL: DepartmentBussinessLogic.cs, EmployeeBussinessLogic.cs gọi lại các hàm CRUD dưới DAL và truyền tham số phù hợp
  • UI: FormDepartment.cs, FormEmployee.cs, FormMain.cs bạn có thể tách ra dự án riêng và add thư viện dự án chứa các lớp cơ sở trên. Gọi các lớp BLL để sử dụng, nhớ khai báo chuỗi kết nối trong app.config (hoặc thiết lập cố định trong class DAL, không khuyến khích). Phần giao diện, nếu muốn chuyên nghiệp, có lẽ nên sử dụng các Component như DevExpress sẽ đẹp, hỗ trợ mạnh mẽ hơn.

2. Sử Mô Hình Phi Kết Nối (Disconnected)

(Video: Đang cập nhật... & Mã nguồn: Sẽ cập nhật cuối bài viết này...)
Says: Có điều lưu ý, về khái niệm kết nối và phi kết nối. Bản thân mô hình phi kết nối này nằm ở chỗ, bạn cần xây dựng một file dữ liệu local trên client như XML, JSON để chứa dữ liệu từ Server. Ngoài ra, các thao tác nghiệp vụ đều lưu tại client, khi yêu cầu thì đồng bộ xuống Database. Như vậy, cho dù mất kết nối mạng, công việc vẫn được tiến hành trên client, vì nó là file nên đóng mở app không mất dữ liệu. Trong demo, chỉ sử dụng bộ nhớ cache DataSet, như vậy thiếu phần lưu local (XML, JSON..) có thể được cập nhật sau.

Step by Step:
s

Created: 12/03/2016 - Editing
Source Code: Implementation for ADO.NET and Entity Framework (Winforms & WPF) 
Video Demo: ADO.NET With Connected Model - Winforms
Video Demo: ADO.NET With Disconnected Model - Winforms
Video Demo: Entity Framework With Database First Approach- WPF 
Video Demo: Entity Framework With Model First Approach - WPF
Video Demo: Entity Framework With Code First Approach - WPF
Read now

3/6/16

[Tips] Quick coding with Snippets in Visual Studio for C#

Snippets sẽ giúp bạn triển khai nhanh một đoạn code với template thiết kế trước. Trong Visual Studio để sử dụng đoạn snippet, ta gõ từ khóa và nhấn Tab Tab VS sẽ generate cho bạn đoạn code mẫu, tiếp tục nhấn Tab để di chuyển nhanh tới các vị trí cần sửa lại hoặc giữ nguyên theo template. (Nhấn Enterđể thoát chế độ chỉnh sửa và xuống dòng, điều này có thể không được hỗ trợ với các phiên bản thấp hơn)


Ngoài các snippets mặc định trong Visual Studio, bạn nên tạo riêng cho mình bộ sưu tập để đáp ứng với nhu cầu công việc. Xem thêm các bước dưới đây nếu bạn quan tâm...

Cấu trúc một template snippet tương tự XML, cú pháp cũng không phức tạp, trước tiên bạn nên copy một vài snippet sẵn ở dưới đây để thực hành. Chi tiết cú pháp ta sẽ nghiên cứu sau:


Add new folder for Snippets & Import more file

Nếu bạn chưa add folder trong Code Snippets  Manager (Tools | Code Snippets Manager.. / Ctrl + K, Ctrl + B) thì cần phải thêm một folder mới có thể import file code snippet
Theo các bước sau đây để thêm mới các file Snippet:

Step 1: Add new folder

Chọn loại ngôn ngữ, sau đó nhấn Add để tiếp tục

Step 2: Select folder

Folder có thể chứa sẵn các file code snippet hoặc rỗng


Step 3: Import new file

Nhấn Add để thêm một hoặc nhiều file code snippet cùng lúc.

Step 4: Choose a location for each code snippet

Chọn từng file và xác nhận  folder chứa nó


OK
Như vậy, lần sau bạn có thể add file code snippet vào thư mục vừa tạo hoặc tạo thêm thư mục mới như đã đề cập ở trên.

References: Template10, MSDN
Created: 06/03/2016
Read now

3/5/16

[Share] Create SwipeList Look As Outlook Windows Mobile 10



References: SwipeListView implement on Windows Universal App
- Tạo controls SwipeList dựa trên ListView hỗ trợ touch sang trái/phải để thực hiện các hành động theo yêu cầu. Bạn có thể thấy điều này tương tự trên Outlook Mail hoạt động với Windows Mobile 10.
- Thao tác touch này chỉ mang lại trải nghiệm tốt với màn hình cảm ứng, đối với desktop truyền thống không có touch screen thì không cần thiết phải thiết kế như vậy

Chú thích:
- Demo này sử dụng lại mã nguồn như đã đề cập ở trên, và triển khai demo ứng dụng Universal cho Windows 10, nhưng để sử dụng được trải nghiệm như đã nói bạn cần chạy demo trên thiết bị cảm ứng như điện thoại, tablet hoặc Emulator tạm thời.
- Nếu bạn muốn custom UI của control này, cần chỉnh sửa tại /Themes/Generic.xaml.Tất nhiên bạn cần có chút hiểu biết về custom Style của control, bất cứ khó khăn về điều này hãy để lại comment.


Created: 05/03/2016
Updated: 05/08/2016
Source Code: DemoSwipeListSolution
Read now