MỚI NHẤT

Thứ Năm, 19 tháng 11, 2015

[SQL] Gộp bảng - Các loại JOIN (inner join, left outer join, right outer join, full join, cross join) trong truy vấn SQL Server

i. Giới thiệu

Mệnh đề Join trong SQL Server dùng để kết nối các bảng, view, sub query lại với nhau thông qua các foreign key hoặc các cột có giá trị tương ứng ở cả hai bảng, view hoặc các sub query.

ii. Chuẩn bị

Trước hết bạn hãy tạo ra hai table rất đơn giản và insert vào đó một ít dữ liệu như đoạn script sau:
create table Item
(
      MaHang nvarchar(20) primary key,
      TenHang nvarchar(200)
)


insert Item(MaHang, TenHang)
      values('NO1700', N'Điện thoại Nokia 1700'),
            ('NO1200', N'Điện thoại Nokia 1200'),          
            ('IPHONE3', N'Điện thoại Iphone 3'),
            ('IPHONE4', N'Điện thoại Iphone 4'),
            ('IPHONE5', N'Điện thoại Iphone 5'),
            ('IPHONE6', N'Điện thoại Iphone 6')


create table OrderDetail
(
      ID int identity primary key,
      NgayDatHang datetime,
      MaHang nvarchar(20),
      SoLuong decimal(19,6) default 0 not null
)


insert OrderDetail(NgayDatHang, MaHang, SoLuong)
      values('20140401', 'NO1700', 5),
            ('20140402', 'NO1700', 1),
            ('20140402', 'IPHONE3', 2),
            ('20140401', 'IPHONE4', 1),
            ('20140401','NO0001', 1000) 

Chúng ta đã có 2 bảng dữ liệu với liên kết như trên, vậy nếu muốn truy xuất cùng lúc thông tin đặt hàng và thông tin hàng thì ta phải làm thế nào? Đây chính là nhiệm vụ của liên kết hay JOIN các bảng lại với nhau.
Trong SQL hỗ trợ các kiểu JOIN như sau:

1. INNER JOIN

INNER JOIN hay viết tắt là JOIN trả về kết quả là tập hợp dữ liệu từ 2 bảng trong đó giá trị dùng để join đều có ở cả 2 bảng, nói cách khác kiểu join này giống phép giao trong tập hợp
Hình minh họa

Câu truy vấn SQL cụ thể như sau:
SELECT t2.MaHang, t1.TenHang, t2.SoLuong
FROM Item t1 INNER JOIN OrderDetail t2 ON t1.MaHang = t2.MaHang

-- Hoặc dạng viết tắt

SELECT t2.MaHang, t1.TenHang, t2.SoLuong
FROM Item t1 JOIN OrderDetail t2 ON t1.MaHang = t2.MaHang

Kết quả là tập hợp sau:
Bốn mã hàng hóa ở cột MaHang đều có trong table Item và table OrderDetail.

2. OUTER JOIN

a. LEFT OUTER JOIN

Viết tắt: LEFT JOIN
Có thể diễn giải LEFT JOIN trong SQL như sau: "Lấy toàn bộ các dòng dữ liệu ở table bên trái và những dòng dữ liệu ở bảng bên phải CÓ giá trị MaHang tồn tại ở bảng bên trái.".
Kết quả minh họa như hình sau, kết quả trả về là hình oval màu xanh:
Câu truy vấn như sau:
SELECT t1.MaHang, t1.TenHang, t2.SoLuong
FROM Item t1 LEFT JOIN OrderDetail t2 ON t1.MaHang = t2.MaHang
Kết quả trả về:
Một số dòng có SoLuong == null là do các MaHang này không tồn tại ở bảng bên phải (OrderDetail), nhưng có tồn tại ở bảng bên trái (Item).

b. RIGHT OUTER JOIN

Viết tắt: RIGHT JOIN
Trái ngược với LEFT JOIN, RIGHT JOIN trong SQL Server lấy toàn bộ dữ liệu của bảng bên phải và dữ liệu của bảng bên trái nhưng giá trị cột JOIN cũng tồn tại trong bảng bên phải.

c. FULL OUTER JOIN

Viết tắt: FULL JOIN

FULL OUTER JOIN trong SQL Server chính là kết quả gộp lại của cả hai table bên trái và bên phải.
Hình minh họa:
Câu truy vấn:
SELECT t1.MaHang, t1.TenHang, t2.SoLuong
FROM Item t1 FULL JOIN OrderDetail t2 ON t1.MaHang = t2.MaHang
Kết quả:
Quan sát kết quả trên có thể thấy:
Các dòng có MaHang = null là do bảng bên phải (OrderDetail) có giá trị nhưng table bên trái (Item) không có giá trị MaHang tương ứng.

Các dòng có SoLuong = null là do các mặt hàng IPHONE5, 6, NO1200 có trong bảng Item nhưng không có dòng nào tương ứng trong table OrderDetail.

d. CROSS JOIN

CROSS JOIN trong SQL ít được sử dụng hơn so với các loại JOIN ở trên do tính ít ý nghĩa của nó, kết quả trả về của CROSS JOIN là lấy số dòng của bảng bên trái x số dòng của bảng bên phải. Ví dụ bảng Item có 6 dòng, bảng OrderDetail có 5 dòng, kết quả trả về là 30 dòng.
Dữ liệu được nhân lên do cứ tương ứng với 1 dòng trong Item thì sẽ nối với toàn bộ 5 dòng trong OrderDetail mà không cần quan tâm đến tiêu chí so sánh nào (không có mệnh đề ON t1.ColumnA = t2.ColumnB như các kiểu JOIN khác). Cái này là phép nhân Đề các 2 quan hệ với nhau.
Câu truy vấn:
SELECT t1.*, t2.*
FROM Item t1 CROSS JOIN OrderDetail t2
Tương tự khi như ta viết:
SELECT t1.*, t2.*
FROM Item t1, OrderDetail t2
Kết quả trả về:
Thường với những câu truy vấn này ta phải thêm điều kiện WHERE để hạn chế kết quả trả về.

Chỉ có liên kết các bảng với nhau mà đã có nhiều cách như vậy. Hy vọng bạn hiểu rõ chức năng của từng loại JOIN ở trên để sử dụng hợp lý.
Chúc bạn thành công!

(Nguồn: Big Data)

Thứ Ba, 24 tháng 6, 2014

[WindowForm] Sử dụng Timer và một số chức năng với Timer

"Timer" là một điều khiển khá hữu ích trong C# - Winform. Timer tương tự như "setInterval" hay "setTimeOut" trong JavaScript đều có chức năng thực hiện một số chức năng nhất định trong các khoảng thời gian lặp lại. Một đoạn chương trình sẽ được lặp đi lặp lại với khoảng nhất định mà không ảnh hưởng đến các tiến trình khác.
Có nhiều loại Timer: System.Windows.Forms.Timer, System.Timers.Timer, System.Threading.Timer. Nhưng để đơn giản bây giờ chúng ta sẽ sử dụng điều khiển Timer của Windows.Forms.
Sử dụng Timer và một số chức năng với Timer

Để khai báo 1 đối tượng Timer cách đơn giản là vào Toolbox tìm "Timer" rồi kéo vào form
Sử dụng Timer và một số chức năng với Timer

Đặt các thuộc tính cho Timer
Sử dụng Timer và một số chức năng với Timer

Trong đó Interval là khoảng thời gian sẽ lặp lại, đơn vị tính miliseconds. Ở ví dụ ta đã bật cho Timer chạy và đặt khoảng thời gian cho nó là 1 giây (1000 miliseconds).

Sự kiện duy nhất của Timer là Timer_Tick cho phép ta thay đổi sự kiện mỗi khi timer lặp lại thời gian. Tức là khi timer lặp lại thì code trong hàm Timer_Tick sẽ được thực hiện.

Bây giờ, tôi sẽ hướng dẫn một vài công dụng với Timer:

- Đồng hồ chạy số trong Window Form

Ta có 2 label để hiển thị thời gian và ngày tháng, 2 label sẽ được thay đổi nội dung sau từng giây. Vậy chúng ta cần 1 điều khiển timer với khoảng lặp là 1000, nội dung Timer_Tick tương tự như sau:
private void timer1_Tick(object sender, EventArgs e)
{
    lblTime.Text = (DateTime.Now.Hour < 10 ? "0" + DateTime.Now.Hour.ToString() : DateTime.Now.Hour.ToString()) + ":" + (DateTime.Now.Minute < 10 ? "0" + DateTime.Now.Minute.ToString() : DateTime.Now.Minute.ToString()) + ":" + (DateTime.Now.Second < 10 ? "0" + DateTime.Now.Second.ToString() : DateTime.Now.Second.ToString());
    lblDate.Text = DateTime.Now.DayOfWeek.ToString() + ", " + (DateTime.Now.Day < 10 ? "0" + DateTime.Now.Day.ToString() : DateTime.Now.Day.ToString()) + "/" + (DateTime.Now.Month < 10 ? "0" + DateTime.Now.Month.ToString() : DateTime.Now.Month.ToString()) + "/" + DateTime.Now.Year;
}

- Ảnh động trong Window Form

Ta đã biết ảnh động thực sự là tập hợp các ảnh tĩnh được hiển thị lần lượt, lặp đi lặp lại sau 1 khoảng thời gian nhất định. Và ở đây ta dùng Timer để đặt cái khoảng thời gian nhất định đó. Mỗi khi đến điểm Tick thì thay đổi ảnh ở trong PictureBox.
/// <summary>
/// Biến kiểm tra ảnh động
/// Không hiểu sao phải dùng thêm 1 biến ngoài để kiểm tra
/// </summary>
private int _img = 1;
private void timer1_Tick(object sender, EventArgs e)
{
    if (_img == 1)
    {
        // Thay đổi ảnh
        pictureBox1.Image = NhacViec.Properties.Resources.Alarm2;
        _img = 2;
    }
    else
    {
        pictureBox1.Image = NhacViec.Properties.Resources.Alarm1;
        _img = 1;
    }
}


Demo về 2 ví dụ này có tại phần mềm Nhắc việc.
Nếu có hứng thú các bạn có thể xem thêm các phần Timer khác và sự khác nhau giữa chúng tại đây.

Thứ Bảy, 21 tháng 6, 2014

[WindowForm] Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

Nhiều chương trình như UniKey, KasperSky, SkyDrive, DropBox... đều có 1 phần chương trình chạy ngầm trong hệ thống và có 1 biểu tượng icon nhỏ ở khay hệ thống - system tray. Bạn có 1 chương trình yêu cầu phải chạy liên tục và chạy ẩn (không hiện ở taskbar), có 1 biểu tượng ở khay hệ thống để người dùng có thể tương tác với chương trình. Rất đơn giản chúng ta sẽ sử dụng NotifyIcon cho việc này.
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

1. Sử dụng NotifyIcon

- Các bạn search ở ToolBox "NotifyIcon" và kéo vào trong form của mình.

- Các thuộc tính của NotifyIcon:
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

BaloonTipIcon, BaloonTipText, BaloonTipTitle hiện ra như 1 thông báo nhỏ ở khay hệ thống (nếu chúng ta cho hiện).
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

ContextMenuStrip là lựa chọn menu khi ấn chuột phải vào notifyIcon.
Text là phần hiện lên khi ta di chuột vào notifyIcon.
Đặt mặc định cho notifyIcon có Visible hay không!?

- Thiết lập các menu chuột phải cho NotifyIcon
Trong ToolBox ta tìm vào kéo 1 đối tượng ContextMenuStrip.
Thêm các MenuItem cho contextmenu đấy. Ở đây hỗ trợ nhiều loại như MenuItem (giống 1 button), ComboBox, TextBox, Separator (vạch ngăn cách).
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

Thêm sự kiện click cho các MenuItem này.

Để sử dụng ContextMenuStrip này cho NotifyIcon đừng quên thiết lập ở phần NotifyIcon như trên.

2. Ẩn chương trình xuống khay hệ thống

Việc này thực sự chỉ là ẩn chương trình đang chạy và cho hiện 1 cái NotifyIcon lên. NotifyIcon có các MenuItem để tương tác với chương trình đang chạy, như mở chương trình, thoát chương trình..., các chức năng do ta đặt ở phần ContextMenuStrip phía trên. Vì ẩn chương trình và chương trình luôn chạy ngầm nên ta phải tính làm sao để giảm thiểu tài nguyên sử dụng, form chúng ta cho chạy ngầm phải ít tốn tài nguyên, chỉ để thực hiện các chức năng cơ bản (như để gọi các form to hơn) hoặc chỉ là 1 service.

Để thực hiện ẩn chương trình ta thêm 1 button, hoặc gán vào các sự kiện khác (minimize form chẳng hạn)
Sự kiện click của button này như sau
private void btnExit_Click(object sender, EventArgs e)
{
 // Cho hiện notifyIcon
    notifyIcon1.Visible = true;
 // Hiện BaloonTip hoặc không
    notifyIcon1.ShowBalloonTip(10);
 
 // Chọn ẩn
    this.Hide();
 // Hoặc
    this.ShowInTaskbar = false;
 WindowState = FormWindowState.Minimized;
 // Hoặc cả 2 để ẩn form
}

Phần việc còn lại là do NotifyIcon phụ trách. Chẳng hạn ta muốn click chuột phải để hiện menu context, click chuột trái để mở form: Ta thêm 1 sự kiện Click hoặc MouseClick cho NotifyIcon
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
    if(e.Button == System.Windows.Forms.MouseButtons.Left)
 {
  // Ẩn notifyIcon đi
  notifyIcon1.Visible = false;
  // Cách này
  WindowState = FormWindowState.Normal;
  this.ShowInTaskbar = true;
  // Hoặc
  this.Show();
  // Hoặc cả 2 miễn là phải tương ứng với lúc ẩn
 }
}

Thứ Sáu, 20 tháng 6, 2014

[WindowForm] Customize Form - Tùy chỉnh form, tạo form có hình dạng bất kỳ

Bạn thấy nhiều phần mềm có những form có hình dạng rất lạ (không phải hình chữ nhật, có border thông thường). Bạn hoàn toàn có thể tạo những form mang hình dạng đặc biệt tùy ý một cách đơn giản.
Customize Form - Tùy chỉnh form, tạo form có hình dạng bất kỳ
Như Photoshop chẳng hạn

Sau đây tôi sẽ hướng dẫn các bạn cách tạo 1 form tùy ý và các thao tác liên quan.

1. Tạo form với hình dạng tùy ý

Thực chất việc này là đặt 1 hình ảnh làm nền cho form rồi cho những phần còn lại "biến mất".
Customize Form - Tùy chỉnh form, tạo form có hình dạng bất kỳ

- Đầu tiên bạn thiết kế 1 cái hình ảnh làm nền cho form. Những phần không cần thiết thì bạn nên để trong suốt, rồi xuất ra ảnh .PNG

- Tiếp theo đặt "BackColor" của form là White, "BackgroundImage" là hình ảnh vừa tạo, FormBorderStyle None

- Đây là phần quan trọng nhất: Cuộn xuống chọn "TransparencyKey" là White => Nó sẽ tìm tất cả phần nào của background form màu trắng để làm trong suốt phần đó. 
Cách này vô cùng đơn giản, để có thể tạo được 1 form tùy ý. Chính vì thế mà nó có nhiều chỗ không trong suốt cho lắm, đặc biệt là những đường giao nhau giữa 2 màu, đoạn đường chéo... Những điểm này khá nhỏ vẫn có thể chấp nhận được. Nếu bạn muốn có nó một cách hoàn hảo + opacity của từng phần trong form thì phải dùng đến phần xử lý đồ họa.

2. Di chuyển cho form tùy chỉnh

Với 1 form đã tạo được như trên vấn đề là khi ta loại bỏ border của form thì làm sao để di chuyển form đây??? Chỉ còn cách code!!!  :)
Việc code còn đem lại cho ta những tùy chọn về di chuyển form do ta tự quyết định: chẳng hạn có cho form "chui ra phía ngoài màn hình" không hoặc là bị bó hẹp trong khuôn khổ của màn hình, cho phép người dùng click chuột ở đâu để di chuyển form???

Trong phần global ta khai báo các biến toàn cục như sau:
/// <summary>
/// Di chuyển form
/// </summary>
private bool drag = false;
private Point dragCursor, dragForm;

Quay lại phần thiết kế để double click và thêm 3 sự kiện: MouseDown, MouseMove, MouseUp cho form.
Chỉnh sửa các sự kiện đấy như sau:
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    drag = true;
    dragCursor = Cursor.Position;
    dragForm = this.Location;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    int wid = SystemInformation.VirtualScreen.Width;
    int hei = SystemInformation.VirtualScreen.Height;
    if (drag)
    {
        // Phải using System.Drawing;
        Point change = Point.Subtract(Cursor.Position, new Size(dragCursor));
        Point newpos = Point.Add(dragForm, new Size(change));
        // QUyết định có cho form chui ra ngoài màn hình không
        if (newpos.X < 0) newpos.X = 0;
        if (newpos.Y < 0) newpos.Y = 0;
        if (newpos.X + this.Width > wid) newpos.X = wid - this.Width;
        if (newpos.Y + this.Height > hei) newpos.Y = hei - this.Height;
        this.Location = newpos;
    }
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    drag = false;
}

Như vậy hiện tại bạn có thể click vào bất cứ phần nào không trong suốt của form để di chuyển form.

3. Thêm một số phần khác

Khi loại bỏ border thì đồng nghĩa với việc không còn các nút Minimize, Maximize, Exit và box-shadow của form. Vậy ta phải thêm thủ công như sau

Thêm các nút điều khiển

Tự thiết kế hình ảnh cho các nút hoặc đơn giản chỉ là các button thông thường. Sau đó thêm sự kiện click như sau
private void btnMini_Click(object sender, EventArgs e)
{
    this.WindowState = FormWindowState.Minimized;
}

private void btnExit_Click(object sender, EventArgs e)
{
    Application.Exit();
} 

Thêm box shadow cho form 

Chúng ta phải override 1 thủ tục của form như sau:
/// <summary>
///  Drop Shadow cho form
/// </summary>
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        // Bóng đổ
        cp.ClassStyle |= 0x20000;
        // Load các control cùng lúc
        cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
        return cp;
    }
}

Phần load các control 1 lúc có thể áp dụng cho các form khác, form có nhiều control. Chẳng hạn form bạn có rất nhiều control và thường xuyên phải Visible/Invisible chúng lần lượt. Như vậy khi các control hiện lên sẽ bị trễ nhìn rất mất mỹ quan. Khi thêm phần này vào thì các control sẽ hiển thị ra cùng 1 lúc, không có hiện tượng trễ.

Thứ Tư, 18 tháng 6, 2014

[WindowForm] Các cách lưu thông tin cài đặt cho ứng dụng C# - Apps setting

Đôi khi chúng ta cần lưu trữ thông tin nào đó liên quan đến người dùng, do người dùng cài đặt. Những thông tin này phải được lưu trữ một cách lâu dài, xuyên suốt từ phiên làm việc này đến phiên làm việc khác. Tức là ta phải có cách để lưu thông tin cài đặt của người dùng

Có nhiều cách để lưu thông tin cài đặt chương trình, sau đây là một số cách phổ biến, dễ sử dụng

1. Lưu thông tin cài đặt vào Registry

Registry là bộ nhớ lưu trữ các thông tin cài đặt của hệ điều hành cũng như của các phần mềm trên nó. Do vậy ta có hoàn toàn có thể lưu trữ và lấy các thông tin trên Registry.

Ưu điểm của cách này là truy xuất nhanh, ít bị thay đổi bởi người không hiểu biết, người dùng và chỉ có lập trình viên mới có thể biết được cấu trúc, vị trí lưu trên Registry.

Nhược điểm là khi muốn lưu, đọc dữ liệu trên Registry đều phải thực thi nhiều code và yêu cầu lập trình viên phải nắm vững cấu trúc của Registry. Các thông tin cài đặt này chỉ có tác dụng với máy đã tạo ra, khi copy ứng dụng sang máy khác thì thông tin cài đặt bị mất.

2. Lưu trực tiếp trên phần mềm

Nền tảng .NET FrameWork cho phép người dùng phần mềm chỉnh sửa và lưu các thông tin cài đặt ngay trên ứng dụng. Cách lưu thông tin cài đặt này rất dễ sử dụng, lập trình. Khi thêm 1 đối tượng setting thì .NET tự động sinh ra 1 class để quản lý các thông tin setting đó.

Để bắt đầu với cách này bạn click đúp vào "Properties" trong tab "Solution Explorer". Sau đó trong tab "Settings" hãy thêm những trường cài đặt mong muốn. Ở đây .NET hỗ trợ nhiều kiểu dữ liệu: bool, string, int, datetime...
Các cách lưu thông tin cài đặt cho ứng dụng C# - Apps setting

Sau khi đã lưu các thông số này, chúng ta đọc, lưu thông tin vào như sau:
// Đọc thông tin
string MySetting = ShowGridView.Properties.Settings.Default.MySetting;

// Ghi thông tin
ShowGridView.Properties.Settings.Default.CheckBox = true;
// Lưu lại
ShowGridView.Properties.Settings.Default.Save();

3. Lưu trên file bên ngoài

Một cách lưu trữ thông tin cài đặt nữa là lưu chúng ra một file text thông thường hoặc một file được mã hóa. Với cách này cũng có nhiều kiểu lưu trữ, tùy vào cách xử lý của lập trình viên:
  • Lưu vào 1 file text thông thường đặt cùng thư mục của ứng dụng. Các thông tin sẽ được lưu trữ theo tiêu chuẩn của lập trình viên. Sau đó lập trình viên phải đọc nội dung của file và xử lý chuỗi để lấy được các thông tin đã ghi trước đó.
  • Lưu vào 1 file XML với quy cách nhất định. Với cách này khi dùng các thủ tục đọc, ghi xml thì công việc đọc, lưu thông tin cài đặt sẽ dễ dàng hơn.
  • Lưu file vào thư mục AppData của từng User. Khi đó với các User khác nhau cùng sử dụng máy tính sẽ có những thông tin cài đặt khác nhau.
  • Lưu thông tin ra file .INI. Cách này bạn có thể tham khảo tại đây.
Vì các thông tin được lưu trên một file riêng biệt nên người dùng có thể dễ dàng thay đổi, hoán chuyển các thông tin cài đặt khi cần thiết (chỉ cần việc cut/paste file ra 1 chỗ khác).

Chủ Nhật, 18 tháng 5, 2014

[ASSEMBLY] Chia sẻ code một số bài toán

Cuối tuần rảnh rỗi, dở hợp ngữ ra học, sau một hồi mày mò, nghịch nghịch viết được mấy chương trình chia sẻ cho mọi người:
[ASSEMBLY] Chia sẻ code một số bài toán



Máy tính đơn giản


Chương trình thực hiện các phép tính đơn giản như cộng trừ nhân chia. Phạm vi số: 16bit, số nguyên dương:
; ScanNum luu trong BX
ScanNum MACRO
 LOCAL Nhap, KetThuc
 PUSH AX
 MOV BX, 0
 Nhap: 
  MOV AH, 1
  INT 21h
  CMP AL, 13
  JE KetThuc
  PUSH AX
  MOV AX, BX
  MUL ten
  MOV BX, AX
  POP AX
  AND AL, 0fh
  ADD BL, AL
 JMP Nhap
 KetThuc:
 POP AX
ENDM
; Macro in text
PrintText MACRO n
 PUSH AX
 PUSH DX
 MOV DL, n
 OR DL, 30h  ; Chuyen so thanh ma ASCII tuong ung
 MOV AH, 2
 INT 21h
 POP DX
 POP AX
ENDM

; Chuogn tring chinh
.MODEL SMALL
ORG 100H
.DATA
 MSG1 DB "   My calculators", 0Ah, 0Dh, "$"
 MSG2 DB "Input a: $"
 MSG3 DB 0Ah, 0Dh, "Operator: (+, -, *, /): $"
 MSG4 DB 0Ah, 0Dh, "Input b: $"
 MSG5 DB 0Ah, 0Dh, "Result: $"
 num1 DW ?
 num2 DW ?
 oper DB ?
 ten DW 10
.CODE
 MOV AX, @DATA
 MOV DS, AX
 
 MOV AH, 9
 LEA DX, MSG1
 INT 21h
 LEA DX, MSG2
 INT 21h
 ; Nhap so 1
 ScanNum
 MOV num1, BX
 ; Print label
 MOV AH, 9
 LEA DX, MSG3
 INT 21h
 ; Nhap phep tinh
 MOV AH, 1
 INT 21h
 MOV oper, AL
 ; Print label
 MOV AH, 9
 LEA DX, MSG4
 INT 21h
 ; Nhap so 2
 ScanNum
 MOV num2, BX
 
 CMP oper, '+'
 JE PhepCong
 
 CMP oper, '-'
 JE PhepTru
 
 CMP oper, '*'
 JE PhepNhan
 
 JMP PhepChia
 
 PhepCong:
  MOV AX, num1
  MOV BX, num2
  ADD AX, BX
  JMP Exit
 PhepTru:
  MOV AX, num1
  MOV BX, num2
  SUB AX, BX
  JMP Exit
 PhepNhan:
  MOV DX, 0
  MOV AX, num1
  MOV BX, num2
  MUL BX   ; AX = AL * BL
  JMP Exit
 PhepChia:
  MOV DX, 0
  MOV AX, num1
  MOV BX, num2
  DIV BX   ; AX = AL / BL
 Exit:
  ; Print Label
  PUSH AX
  MOV AH, 9
  LEA DX, MSG5
  INT 21h
  POP AX
  ; Print res

 MOV CX, 1   ; Co danh dau
 MOV BX, 10000
 Begin_Print: 
  CMP BX, 0
  JE End_Print ; BX = 0
  
  CMP CX, 0
  JE Calc   ; CX = 0
  
  CMP AX, BX
  JB Skip   ; AX < BX
 Calc:
  MOV CX, 0
  MOV DX, 0
  DIV BX   ; AX = DX AX / BX
  PrintText AL ; In AL nhu 1 ky tu binh thuong
  MOV AX, DX
  
 Skip:    ; Giam BX 10 lan
  PUSH AX
  MOV DX, 0
  MOV AX, BX
  DIV ten
  MOV BX, AX
  POP AX 
 JMP Begin_Print
 
 End_Print:
  RET
 


Tìm ước chung lớn nhất của 2 số


Nhập vào 2 số 16bit rồi in ra UCLN của chúng:
; MACRO
; MACRO khong lam thay doi gia tri cua bien vao, chi thay doi gia tri thanh ghi
Nhan MACRO reg, num
 LOCAL next, continue, exit
 PUSH AX
 PUSH DX
 PUSH CX
 
 MOV AX, reg
 MOV CX, num
 XOR DX, DX
 next:
  CMP CX, 0
  JE exit
  TEST CX, 1b  ; Ky tu cuoi cua AL = 1=> ZF = 0
  JZ continue  ; ZF = 1
  ADD DX, AX
  continue:
   SHL AX, 1
   SHR CX, 1
  JMP next
 exit:
  MOV reg, DX
 
 POP CX
 POP DX
 POP AX
ENDM

; Nhap so, luu vao AX
ScanNum MACRO
 local Nhap, exit
 PUSH BX
 MOV AH, 1
 XOR BX, BX  ; Tuong duong mov bx, 0
 Nhap:
  INT 21h
  CMP AL, 13
  JE exit
  AND AL, 0Fh
  Nhan BX, 10
  ADD BL, AL
  JMP Nhap
 exit:
  MOV AX, BX
 POP BX
ENDM

; In 1 so bat ky o AX
PrintNums MACRO
 LOCAL next, exit, print
 PUSH BX   ; Cat cac gia tri vao stack
 PUSH CX 
 PUSH DX
 
 MOV BX, 10  ; So chia
 XOR CX, CX  ; MOV CX, 0
 next:
  CMP AX, 0
  JE exit  ; Neu AX = 0 thi dung lai
  XOR DX, DX ; MOV DX, 0
  DIV BX
  PUSH DX  ; DX la so du cua phep chia
  INC CX  ; Tang CX
  JMP next ; Lap lai
 exit:
  MOV AH, 2
  
 print:
  XOR DL, DL ; MOV DL, 0
  POP DX  
  OR DL, 30h ; Chuyen so thanh ma ASCII tuong ung
  INT 21h
  LOOP print ; Lap den khi nao CX = 0
  
 POP DX 
 POP CX 
 POP BX
ENDM

; In so co 1 chu so
PrintNum MACRO reg
 PUSH AX
 PUSH DX
 MOV DL, reg
 MOV AH, 2
 OR DL, 30h
 INT 21h
 POP DX
 POP AX
ENDM

; Tim uoc chung lon nhat, xuat ket qua vao DX
UCLN MACRO m, n
 PUSH AX
 PUSH BX
 
 MOV AX, m
 MOV BX, n
 next:
  CMP AX, BX
  JE exit
  JB less
  SUB AX, BX
  JMP next
 less:
  SUB BX, AX
  JMP next
 exit:
  MOV DX, AX
  
 POP BX
 POP AX
ENDM

; Chuong trinh chinh
.MODEL small
ORG 100h
.DATA
 Enter DB 0Dh, 0Ah, '$'
 num1 DW ?
 num2 DW ?
.CODE
 MOV AX, seg Enter
 MOV DS, AX
 
 ScanNum  ; Xuat ra AL
 MOV num1, AX
 
 PUSH AX
 MOV AH, 9
 LEA DX, Enter
 INT 21h
 POP AX 
 
 ScanNum 
 MOV num2, AX
 
 
 PUSH AX
 MOV AH, 9
 LEA DX, Enter
 INT 21h
 POP AX 
 
 XOR DX, DX
 UCLN num1, num2
 MOV AX, DX
 PrintNums 

Chương trình in ra n số hạng đầu tiên trong dãy Fibonacy


Nhập vào 1 số n (từ 1~22) rồi in ra n số hạng đầu tiên trong dãy Fibonacy
; MACRO
; MACRO khong lam thay doi gia tri cua bien vao, chi thay doi gia tri thanh ghi
Nhan MACRO reg, num
 LOCAL next, continue, exit
 PUSH AX
 PUSH DX
 PUSH CX
 
 MOV AX, reg
 MOV CX, num
 XOR DX, DX
 next:
  CMP CX, 0
  JE exit
  TEST CX, 1b  ; Ky tu cuoi cua AL = 1=> ZF = 0
  JZ continue  ; ZF = 1
  ADD DX, AX
  continue:
   SHL AX, 1
   SHR CX, 1
  JMP next
 exit:
  MOV reg, DX
 
 POP CX
 POP DX
 POP AX
ENDM

; Nhap so, luu vao AX
ScanNum MACRO
 local Nhap, exit
 PUSH BX
 MOV AH, 1
 XOR BX, BX  ; Tuong duong mov bx, 0
 Nhap:
  INT 21h
  CMP AL, 13
  JE exit
  AND AL, 0Fh
  Nhan BX, 10
  ADD BL, AL
  JMP Nhap
 exit:
  MOV AX, BX
 POP BX
ENDM

; In 1 so bat ky o AX
PrintNums MACRO
 LOCAL next, exit, print
 PUSH BX   ; Cat cac gia tri vao stack
 PUSH CX 
 PUSH DX
 
 MOV BX, 10  ; So chia
 XOR CX, CX  ; MOV CX, 0
 next:
  CMP AX, 0
  JE exit  ; Neu AX = 0 thi dung lai
  XOR DX, DX ; MOV DX, 0
  DIV BX
  PUSH DX  ; DX la so du cua phep chia
  INC CX  ; Tang CX
  JMP next ; Lap lai
 exit:
  MOV AH, 2
  
 print:
  XOR DL, DL ; MOV DL, 0
  POP DX  
  OR DL, 30h ; Chuyen so thanh ma ASCII tuong ung
  INT 21h
  LOOP print ; Lap den khi nao CX = 0
  
 POP DX 
 POP CX 
 POP BX
ENDM

.MODEL SMALL
ORG 100h
.DATA
 count DB ?
 Enter DB 0Ah, 0Dh, '?'
 ten DW 10
.CODE
 ScanNum
 MOV count, AL
 
 XOR DX, DX
 
 ; In dau Enter
 MOV AH, 2
 MOV DL, 0Ah
 INT 21h
 MOV DL, 0Dh
 INT 21h
 
 CMP count, 1
 JE in1
 CMP count, 2
 JE in11
 
 OR BX, 1
 PUSH BX
 PUSH BX
 ; In ra '1 1'
 MOV DL, '1'
  INT 21h
  MOV DL, ' '
  INT 21h
  MOV DL, '1'
  INT 21h
  
 SUB count, 2
 ; Dung stack de luu mang cac so Fibonacy
 next:
  MOV AH, 2
  MOV DL, ' '
  INT 21h
  MOV BP, SP
  MOV BX, [BP]
  ADD BX, [BP+2]
  PUSH BX
  MOV AX, BX
  PrintNums
  
  PUSH AX
  MOV AL, count
  DEC AL
  CMP AL, 0
  JE exit
  MOV count, AL
  POP AX
 JMP next
  
 JMP exit
 ; In so Fibonacy
 in1:
  MOV DL, '1'
  INT 21h 
  JMP exit 
 ; In 2 so dau trong day
 in11:
  MOV DL, '1'
  INT 21h
  MOV DL, ' '
  INT 21h
  MOV DL, '1'
  INT 21h
 exit:
  

[ASSEMBLY] In một số nguyên dương bất kỳ

Trong lập trình hợp ngữ, nhiều lúc bạn muốn thực hiện phép nhân hoặc chia nhưng kết quả lại lưu ở trong thanh ghi AX, và bạn lúng túng không biết in chúng ra như thế nào?! Trong bài này tôi sẽ hướng dẫn các bạn 2 cách đơn giản để in ra 1 số bất kỳ (số nguyên dương, 16bit) trong AX.
[ASSEMBLY] In một số nguyên dương bất kỳ


Với cùng 1 tư tưởng đó là: chia số muốn in thành các chữ số riêng biệt, rồi in từng chữ số đó như 1 ký tự bình thường

Nhắc lại: lệnh DIV 
Cú pháp DIV reg   ; AX = AX / reg => kết quả phép chia nguyên lưu vào AX, số dư lưu vào DL

Cách 1: Duyệt các chữ số từ hàng đơn vị, lưu chúng vào Stack rồi in ngược lại

Với cách này chúng ta chia số muốn in thành các chữ số, thực hiện từ chữ số hàng đơn vị cho đến các chữ số có trọng số cao hơn. Để thực hiện ta tiến hành dùng lệnh DIV để lấy ra số dư phép chia AX cho 10 - chính là chữ số hàng đơn vị của AX. Chữ số này sẽ được cất trong Stack, trở thành đáy Stack (trong phạm vi của thủ tục này), quá trình này lặp lại đến khi AX bằng 0, chữ số có trọng số cao nhất sẽ là đỉnh stack, sẽ được in ra đầu tiên.
Dùng biến CX để đếm số ký tự trong số, phục vụ cho việc lặp in.
[ASSEMBLY] In một số nguyên dương bất kỳ

Để in ra, ta lần lượt lấy các giá trị trong Stack  rồi in chúng như những ký tự bình thường. Việc in sẽ thực hiện từ chữ số có trọng số cao nhất đến chữ số có trọng số thấp nhất (hàng đơn vị). Số lần in sẽ do CX kiểm soát.

Code cụ thể như sau:
; In 1 so bat ky o AX
PrintNums MACRO
 LOCAL next, exit, print
 PUSH BX   ; Cat cac gia tri vao stack
 PUSH CX 
 PUSH DX
 
 MOV BX, 10  ; So chia
 XOR CX, CX  ; MOV CX, 0
 next:
  CMP AX, 0
  JE exit  ; Neu AX = 0 thi dung lai
  XOR DX, DX ; MOV DX, 0
  DIV BX
  PUSH DX  ; DX la so du cua phep chia
  INC CX  ; Tang CX
  JMP next ; Lap lai
 exit:
  MOV AH, 2
  
 print:
  XOR DL, DL ; MOV DL, 0
  POP DX  
  OR DL, 30h ; Chuyen so thanh ma ASCII tuong ung
  INT 21h
  LOOP print ; Lap den khi nao CX = 0
  
 POP DX 
 POP CX 
 POP BX
ENDM

Cách 2: Duyệt các chữ số từ hàng cao nhất đến hàng đơn vị, in trực tiếp (không dùng Stack)

Cũng dùng phép chia để phân tách số ban đầu thành các chữ só riêng biệt nhưng lần này lấy kết quả để in trực tiếp (không lấy in số dư như cách trên). Việc in sẽ tiến hành từ ký tự có trọng số cao nhất đến hàng đơn vị.
Trong mỗi bước ta chia AX cho BX = 10000, sau đó giảm BX xuống còn 1000, 100, 10, 1 (cũng dùng phép chia để giảm BX). 
Dùng CX để lưu trạng thái, tránh việc in những số 0 ở đầu kết quả.

Code cụ thể như sau:
Print PROC
 MOV CX, 1   ; Co danh dau
 MOV BX, 10000
 Begin_Print: 
  CMP BX, 0
  JE End_Print ; BX = 0
  
  CMP CX, 0
  JE Calc   ; CX = 0
  
  CMP AX, BX
  JB Skip   ; AX < BX
 Calc:
  MOV CX, 0
  MOV DX, 0
  DIV BX   ; AX = DX AX / BX
  PrintText AL ; In AL nhu 1 ky tu binh thuong
  MOV AX, DX
  
 Skip:    ; Giam BX 10 lan
  PUSH AX
  MOV DX, 0
  MOV AX, BX
  DIV ten
  MOV BX, AX
  POP AX 
 JMP Begin_Print
 
 End_Print:
Print ENDP

Phần PrintText
; Macro in text
PrintText MACRO n
 PUSH AX
 PUSH DX
 MOV DL, n
 OR DL, 30h  ; Chuyen so thanh ma ASCII tuong ung
 MOV AH, 2
 INT 21h
 POP DX
 POP AX
ENDM


Chúc bạn thành công!!!

Thứ Tư, 23 tháng 4, 2014

[SQLExpress] Lấy bản ghi ngẫu nhiên với SQL và LinQ

Trong nhiều trường hợp ta phải chọn ngẫu nhiên 1 hoặc một số bản ghi trong CSDL như: chọn 5 bài đăng ngẫu nhiên trong blog, chọn 1 câu hỏi ngẫu nhiên cho chương trình trả lời câu hỏi...
Trong cú pháp của SQL, LinQ đều có cách để làm việc này

I. SQL query lấy bản ghi ngẫu nhiên

Lấy bản ghi ngẫu nhiên với SQL và LinQ

Cấu trúc
SELECT TOP 5 [IDpost]
  FROM [dbo].[tbPost]

  ORDER BY NEWID()  -- Trình tự sắp xếp ngẫu nhiên

Trong đó NEWID() quy định 1 trình tự sắp xếp mà các bản ghi được sắp xếp ngẫu nhiên, đây chính là cơ sở để lấy các bản ghi ngẫu nhiên.

II. Lấy bản ghi ngẫu nhiên bằng code LINQ

Dùng phương thức SKIP() của IEnumerable để nhảy qua n bản ghi, với n là một số ngẫu nhiên. Thực chất cách này không phải là lấy ngẫu nhiên một số bản ghi mà nếu có thì cũng chỉ hiệu quả với bài toán lấy ngẫu nhiên 1 bản ghi duy nhất.
Lấy bản ghi ngẫu nhiên với SQL và LinQ

Cấu trúc của cách làm này như sau:
var p = from post in db.tbPosts
  select new { post.IDpost, post.title };  // Chọn dữ liệu từ LinQ

int count = p.Count();
var random = new System.Random();                   // Khởi tạo biến random
var postRD = p.Skip(random.Next(count)).Take(5);    // Tiến hành random và chọn 5 record đầu tiên
dataSet1BindingSource.DataSource = postRD;          // Điền dữ liệu vào datagridview

Theo code này thì bạn sẽ lấy được 5 bản ghi liền nhau ở vị trí ngẫu nhiên > sẽ có lúc nhận được không đủ 5 bản ghi. Không đúng với bài toán lắm.
Vậy giải pháp ở đây là chạy câu lệnh SQL chửa NEWID() bằng LINQ
var postRD = db.ExecuteQuery<tbPost>("SELECT * FROM tbPost ORDER BY NEWID()").Take(5);
dataSet1BindingSource.DataSource = postRD;          // Thiết lập dữ liệu cho binddingridview


Chủ Nhật, 20 tháng 4, 2014

[LINQ] LinQ là gì và tại sao nên dùng LinQ?

Với SQLExpress để truy vấn dữ liệu ta phải dùng đến các câu lệnh - Query khá phức tạp. Hơn nữa để sử dụng trong ứng dụng C# lại thêm 1 tầng phức tạp nữa với các câu lệnh: dùng ConnectionString khởi tạo kết nối tới DataBase, tự khai báo các biến để chạy 1 lệnh - command, rồi còn phải tính toán đầu ra của câu lệnh... Thật là quá phức tạp nếu như ta có 1 chương trình "khủng".
Vậy làm sao để giải quyết vấn đề này? 
Một đề xuất là sử dụng Linq to SQL.
Không chỉ áp dụng cho truy vấn SQL mà LinQ còn có khả năng hỗ trợ trên nhiều nền tảng khác: XML, SQLite, Excel...

I. LinQ là gì?

LinQ là gì và tại sao nên dùng LinQ

Để giảm gánh nặng thao tác trên nhiều ngôn ngữ khác nhau và cải thiện năng suất lập trình, Microsoft đã phát triển giải pháp tích hợp dữ liệu cho .NET Framework có tên gọi là LINQ (Language Integrated Query), đây là thư viện mở rộng cho các ngôn ngữ lập trình C# và Visual Basic.NET (có thể mở rộng cho các ngôn ngữ khác) cung cấp khả năng truy vấn trực tiếp dữ liệu Object, CSDL và XML.
LINQ là một tập hợp các thành phần mở rộng cho phép viết các câu truy vấn dữ liệu ngay trong một ngôn ngữ lập trình, như C# hoặc VB.NET. Khi tạo một đối tượng LINQ thì Visual Studio sẽ tự động sinh ra các lớp có các thành phần tương ứng với CSDL của chúng ta. Khi muốn truy vấn, làm việc với CSDL ta chỉ việc gọi và truy xuất các hàm, thủ tục tương ứng của LINQ mà không cần quan tâm đến các câu lệnh SQL thông thường.
Tóm lại LINQ ra đời để giảm công sức cho những quá trình đơn giản và “chung chung” trước đây.

Điểm mạnh (chưa chắc về độ mạnh, nhưng hay) của LINQ là “viết truy vấn cho rất nhiều các đối tượng dữ liệu”. Từ CSDL, XML Data Object … thậm chí là viết truy vấn cho một biến mảng đã tạo ra trước đó. Vì vậy mới có các khái niệm LinQ to SQL, LinQ to XML, blo bla ….
Tuy nhiên so với mô hình Entity (Entity Framework), LINQ có yếu điểm là chậm và thiếu nhất quán (hiện đại tất phải hại điện).

LINQ có từ bản .NET 3.5, vậy nên tối thiểu chương trình của bạn phải chạy trên nền tảng này.
Visual Studio 2008, hoặc các phiên bản Express của nó là các bộ công cụ phát triển tiêu biểu cho ứng dụng dùng LINQ.

II. Sử dụng LinQ

LinQ là gì và tại sao nên dùng LinQ
Câu lệnh SELECT trong SQL được thực hiện bởi LINQ
Trong phần này tôi sẽ sử dụng 1 project demo để các bạn thấy được cách làm việc với LINQ như thế nào?!
CSDL là 1 bảng tbTest với 2 trường: id (kiểu int, tự động tăng - Identity) và Feild1 (kiểu nvarchar(50)).

1. Khởi tạo đối tượng LinQ to SQL

Trong project chọn Add > Data > LinQ to SQL classes

LinQ là gì và tại sao nên dùng LinQ?

Ở đây tôi tạo 1 file DB.dbml trong thư mục DB để dễ quản lý.
Sau khi có được file ta tiến hành kéo các table cần thiết vào để tự động sinh các thủ tục LinQ
LinQ là gì và tại sao nên dùng LinQ?

Vậy là xong, ta đã tạo được các thủ tục cần thiết để làm việc với LINQ. Easy??!!   :)

2. Truy vấn dữ liệu

Tương tự như Entity ta phải khai báo 1 biến DataContext để tương tác với LinQ
DB.DBDataContext db = new DB.DBDataContext();  

Có 2 kiểu truy vấn dữ liệu:
Query Syntax
var abc = from p in db.tbTests
          where p.id > 10
          select p;

// Hoặc chọn một số trường
var abc = from p in db.tbTests
          where p.id > 10
          select new
          {
              p.id,
              p.Feild1
          };
Method Syntax
var xyz = db.tbTests.Where(p => p.id > 10).Select(p => new { p.id, p.Feild1 });

Câu truy vấn SQL tương ứng
SELECT [id]
      ,[Feild1]
  FROM [dbo].[tbTest]
  WHERE [id] > 10

Chọn từ nhiều bảng theo kiểu Inner Join (lấy những bản ghi có điều kiện thỏa mãn)
// Query Syntax
var result = from p in products
             join c in categories on p.CategoryID equals c. CategoryID
             select new
             {
                 ProductName=p.ProductName,
                 CategoryName=c.CategoryName
             };

// Hoặc chọn từ 2 bảng bằng cách from 2 lần  :)
var result = from p in products
             from c in categories
             where p.ProductName equals c.CategoryName
             select new
             {
                 ProductName=p.ProductName,
                 CategoryName=c.CategoryName
             };

// Method Syntax
var result = products.Join(
             categories,
             p=>p.CategoryID,
             c=>c.CategoryID,
             (p,c) => new
             {
                 ProductName=p.ProductName,
                 CategoryName=c.CategoryName
             });

Cú pháp khác tương tự các câu lệnh trong SQL.
Các biến ở trên trả về có kiểu IEnumrable, 1 loại kiểu dữ liệu giống như List. Các thao tác cơ bản với loại biến này:

  • xyz.FirstOrDefault(): Chọn bản ghi đầu tiên hoặc mặc định
  • xyz.Skip(5): Nhảy qua n bản ghi
  • xyz.Take(5): Lấy n bản ghi đầu tiên
  • xyz.ToList(): Chuyển sang kiểu List
  • xyz.Count(): đếm số bản ghi
  • xyz.Select(...), xyz.Where(...), xyz.Join(...): Các câu lệnh truy vấn theo kiểu Method Syntax
  • bla bla

Đôi khi bạn không tìm được cú pháp thích hợp hoặc LinQ không hỗ trợ loại truy vấn mà vốn có trong SQL thì bạn có thể thực hiện trực tiếp câu lệnh đó thông qua LinQ:
var result = db.ExecuteQuery<int>("SELECT NEXT VALUE FOR seq_tbCanBo")

3. Thêm, sửa, xóa dữ liệu thông qua LinQ

Thêm dữ liệu
DB.tbTest a = new DB.tbTest();      // Khai báo đối tượng mới
a.Feild1 = txtFeild1.Text;      // id là giá trị tự động tăng > ko cần thay đổi
db.tbTests.InsertOnSubmit(a);   // Thêm đối tượng a vào
db.SubmitChanges();     // Lưu thay đổi

Sửa dữ liệu
var a = (from p in db.tbTests
         where p.id == int.Parse(txtId.Text)
         select p).FirstOrDefault();
a.Feild1 = txtFeild1.Text;
db.SubmitChanges();

Xóa dữ liệu

var a = (from p in db.tbTests
         where p.id == int.Parse(txtId.Text)
         select p).FirstOrDefault();
db.tbTests.DeleteOnSubmit(a);
db.SubmitChanges();

III. Bindding

Bindding là cách thuận tiện để thay đổi, cập nhật, thêm mới bản ghi ở CSDL một cách dễ dàng trực quan, sử dụng LinQ.
Giả sử ta thực hiện Bindding ở 1 bảng, có 2 chế độ (kiểu hiển thị) là GridView Detail:
  • Chế độ GridView: có 1 gridview để hiển thị các bản ghi trong bảng, tương tự như khi chúng ta chạy câu truy vấn SELECT * trong SQL
  • Detail: các Control cho phép thay đổi giá trị của bản ghi đang được chọn ở Gridview. Khi click vào 1 hàng ở Gridview thì dữ liệu của hàng đó sẽ được điền tự động vào các Control này.

Cách dùng Bindding:
Trong chế độ Design form, mở cửa sổ Data Sources, ở đây các bảng trong file DB.dbml (được tạo khi khởi tạo LinQ) sẽ được hiển thị, giúp ta có thể kéo vào trong form của mình
Với mỗi bảng có các tùy chọn để chọn chế độ xem: Gridview, Detail,...
LinQ là gì và tại sao nên dùng LinQ?
Tạo Bindding bằng cách kéo thả
Sau khi kéo như vậy thì nó sinh ra 1 đối tượng là tbTestBinddingSource, đây chính là đối tượng tương tác với SQL, LinQ.
Quy định nguồn dữ liệu cho Bindding:
// DataSource là 1 bảng có sẵn
tbTestBindingSource.DataSource = db.tbTests;

// Datasource là một đối tượng IEnumrable lấy từ truy vấn LINQ
tbTestBindingSource.DataSource = result;

Bạn có thể kéo 1 BinddingNavigator để thực hiện các thao tác thêm, xóa dễ dàng
LinQ là gì và tại sao nên dùng LinQ?

Khi đã có Bindding như thế này rồi thì việc thêm sửa xóa cực kỳ đơn giản, không cần code nhiều, sau khi thay đổi trên gridview, detail để lưu tất cả các thay đổi chỉ cần
tbTestBindingSource.EndEdit();
db.SubmitChanges();

Các thao tác có thể làm với BinddingSource
tbTestBindingSource.RemoveCurrent();    // Xóa hàng hiện tại

// Di chuyển trên gridview
tbTestBindingSource.MoveFirst();
tbTestBindingSource.MoveLast();
tbTestBindingSource.MoveNext();
tbTestBindingSource.MovePrevious();

tbTestBindingSource.Position = 5;   // Xác định vị trí cho Bindding

Sau số thao tác thay đổi trên grid view, bạn muốn xem số hàng thêm mới, sửa xóa??
int insert = db.GetChangeSet().Inserts.Count;
int update = db.GetChangeSet().Updates.Count;
int delete = db.GetChangeSet().Deletes.Count;


Tham khảo project demo trên tại đây.
Các bạn có thể truy cập liên kết để có thêm thông tin, các thao tác với LINQ.

Thứ Bảy, 19 tháng 4, 2014

[Windows Form] DevExpress - thư viện lập trình cho windows form với một số thủ thuật

DevExpress là 1 hệ thống thư viện lập trình cực hữu ích cho việc thiết kế, lập trình form 1 cách đơn giản, chuyên nghiệp.
DevExpress bao gồm rất nhiều Control (gần như có thể thay thế hoàn toàn các Control của .NET) và còn nhiều Control ghép, mở rộng mà .NET không có. Nó chứa từ các điều khiển cơ bản như TextEdit, Button, MessageBox, PictureBox, GridView... đến các điều khiển mở rộng, nâng cao như SearchLookupEdit, RibbonBar, SpreadSheet Control... Các điều khiển tích hợp nhiều chức năng, tùy chỉnh giúp người lập trình bớt phải code.

Điểm đặc biệt ở Dev là nó hỗ trợ nhiều Skin khác nhau, theo ý tôi thì chúng đều rất đẹp và nhìn có vẻ rất chuyên nghiệp, lập trình viên có thể để người dùng chọn Skin ngay trong khi chạy chương trình.
Vì nhiều tính năng như vậy nên bộ thư viện cũng khá là nặng và tốn thời gian khi chạy chương trình trong lần đầu load form.

Trang chủ: https://www.devexpress.com/
Download (cracked): Bản 13.1.4 (hiện nay đã có bản 13.2)

Sau đây tôi xin giới thiệu một số thủ thuật, cách sử dụng Dev hiệu quả hơn

I. Tạo form PreLoad cho form chính

Với 1 chương trình tương đối lớn, nhiều control cần load khi khởi tạo, chạy lần đầu thì việc phải đợi lâu, độ delay lớn sẽ gây cảm giác không tốt tới người dùng. Điều chúng ta có thể làm là thử tạo 1 form pre load cho main form. Tức là trong khi đang load form chính (tốn thời gian) thì ta cho hiển thị 1 form splash nhẹ hơn lên trước, sau khi form chính load xong thì form splash này mất đi. Trong form splash này có thể cho hiển thị tên phần mềm, copyright, progress bar... để người dùng không có cảm giác phải đợi lâu.

Để tạo được 1 from pre load ta làm theo các bước sau:
- Trong Project tạo 1 form DevExpress splashForm, ta sửa form này theo ý muốn ( như hình trên chẳng hạn)
- Trong form chính kéo 1 control "splashScreenManager" vào và đặt thuộc tính "ActiveSplashFormTypeInfo" cho nó là tên form splash vừa tạo ở trên. Có thể tùy chỉnh thêm 1 số tùy chọn.

II. Áp dụng, thay đổi skin cho form

Thay đổi giao diện áp dụng với form Ribbon. Có nhiều skin như Office 2013, Win 7, Mac...
Để thay đổi được cả giao diện ribbon và giao diện form phải cài đặt thuộc tính "RibbonStyle" của thành phẩn Ribbon Control là "Office2013".

Trong 1 RibbonPage > RibbonPageGroup nào đó bạn tạo 1 "RibbonGalleryBarItem", đặt tên cho nó (là rbiGallery chẳn hạn)

Trong phần code ta làm như sau:
using DevExpress.Skins;
using DevExpress.LookAndFeel;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraBars.Ribbon.Gallery;

//
//
namespace ABC
{
    public partial class XYZ : DevExpress.XtraBars.Ribbon.RibbonForm
    {
        public XYZ()
        {
            InitializeComponent();
            // Gallery Skin
            DevExpress.XtraBars.Helpers.SkinHelper.InitSkinGallery(rbiGallery, true);
            UserLookAndFeel.Default.SetSkinStyle("Default");

Thêm nhiều skin hơn bằng cách sửa file "Program.cs", thêm đoạn sau vào:
DevExpress.UserSkins.BonusSkins.Register();
DevExpress.Skins.SkinManager.EnableFormSkins();

III. Sử dụng MessageBox của DevExpress

Việc sửa giao diện cho form đã ổn, vấn đề là những MessageBox của .NET vẫn chưa được thay đổi và không đồng bộ với giao diện của form. Vậy làm sao để khắc phục?
Dev cũng hỗ trợ cả cái MessageBox này với tên "XtraMessageBox", việc sử dụng XtraMessageBox cũng giống hệt khi ta sử dụng MessageBox. Thuận tiện hơn nữa là MessageBox này cũng thay đổi giao diện khi ta thay đổi giao diện của form.

Sử dụng XtraMessageBox như sau:
using DevExpress.XtraEditors;   // MessageBox
//
//
XtraMessageBox.Show("Có lưu file không?", "File chưa được lưu", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

Như vậy là phần lớn các Control của form đã có thể thay đổi, tùy chỉnh với Dev.

Thứ Sáu, 18 tháng 4, 2014

[ASSEMBLY] Biên dịch mã nguồn Assembly sử dụng Tasm + Tlink và emu8086

I. Biên dịch Assembly bằng Tasm - Turbo ASM

Để chạy được file *.asm ta làm như sau:
Download file Tasm Tlink (trong 1 file nén) tại đây.
B1: Soạn thảo nội dung assembly vào 1 file văn bản thông thường, lưu lại với đuôi (định dạng) .asm
B2: Copy file trên cùng 2 file đã giải nén vào ổ D (cho dễ lấy địa chỉ)
B3: Vào cmd (Nhấn đồng thời phím Window + 'R', gõ 'cmd', Enter), trỏ đến ổ D hoặc 1 nơi nào khác lưu các file được đề cập đến ở trên dùng lệnh 'cd'
B4: Thực hiện biên dịch file .asm sang file object: Gõ 'tasm ' + tên file asm, Enter
B5: Biên dịch, gộp file object thành file .exe: Gõ 'tlink' + tên file object, Enter
Kết quả cho ra 1 file .exe.

Lưu ý: Máy window 64bit mà không chạy được 2 file này thì tham khảo tại đây.

II. Chạy Assembly bằng emu8086

'emu8086' là 1 phần mềm cho phép soạn thảo, biên dịch, chạy chương trình Assembly
Tải về chương trình cài đặt và crack tại đây.
Sau khi tải về tiến hành cài đặt và chạy file 'SND-E8086407-KG.exe' để lấy key crack.

Phần mềm hỗ trợ các chức năng:

  • Soạn thảo mã nguồn assembly với highlight
  • Biên dịch mã nguồn sang file .exe
  • Chạy chương trình theo từng dòng lệnh (step)
  • Hiển thị giá trị của các thanh ghi trong từng step
  • Ngoài ra còn có nhiều thông tin bổ trợ như: code mẫu các chương trình đơn giản, bảng mã ASCII...
Giao diện chương trình:
Giao diện và các phím chức năng cơ bản

Chạy chương tình bằng emu8086