Thứ Ba, 31 tháng 7, 2012

Sử dụng LINQ để truy vấn dữ liệu trong 1 DataTable

Trước hết phải add reference System.Data.DataSetExtensions.dll để sử dụng phương thức extension AsEnumerable() cho DataTable.

Demo:
  1. // tạo 1 datatable để test  
  2. DataTable table = new DataTable("table");  
  3. table.Columns.Add(new DataColumn("Name"typeof(string)));  
  4. table.Columns.Add(new DataColumn("Age"typeof(int)));  
  5. for (int i = 0; i < 5; i++)  
  6. {  
  7.     DataRow NewRow = table.NewRow();  
  8.     NewRow["Name"] = "Nguyễn Văn " + i;  
  9.     NewRow["Age"] = i;  
  10.     table.Rows.Add(NewRow);  
  11. }  
  12.   
  13. // lấy danh sách những người có tuổi >= 3  
  14. var query = from row in table.AsEnumerable() where row.Field<int>("Age") >=3 select row;  
  15. DataTable dt = query.CopyToDataTable();  
DataTable gốc:


DataTable từ câu truy vấn:


Thứ Hai, 30 tháng 7, 2012

Cấu hình thông báo lỗi 404 not found cho website trong web.config

Thông báo lỗi 404 not found khi người dùng truy cập vào 1 đường dẫn không tồn tại trong website. Việc cài đặt cấu hình sẽ giúp chuyển hướng người dùng đến trang thông báo hoặc chuyển về trang mặc định nào đó khi xảy ra lỗi thay vì hiển thị thông điệp khó hiểu của hệ thống.

Cấu hình trong <system.web>    </system.web>:
  1. <customErrors mode="On" defaultRedirect="~/trang-chu.aspx">  
  2.   <error statusCode="404" redirect="~/thong-bao.aspx"/>  
  3. </customErrors>  
Trong trường hợp đường dẫn không tồn tại (statusCode = 404) trình duyệt sẽ được chuyển tới trang thong-bao.aspx để thông báo hoặc hướng dẫn cho người dùng.

Các trường hợp lỗi khác (statusCode khác) nếu xảy ra nhưng không được cấu hình riêng thì được chuyển về trang mặc định defaultRedirect.

Danh sách mã lỗi( statusCode ) có thể xem tại http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Note:
Cấu hình thông báo lỗi có thể gây khó khăn cho việc test trong quá trình xây dựng website.
Có 3 mode là On, Off và RemoteOnly. Để test thử cấu hình của bạn thì để mode là On, sau đó nên để mode là RemoteOnly, lúc này khi chạy ứng dụng ở local bạn vẫn  sẽ nhận được thông báo lỗi của hệ thống nếu có lỗi xảy ra.

Chủ Nhật, 29 tháng 7, 2012

Restore database vào một vị trí mới và đặt lại tên cho database

Đôi khi ta chuyển database từ server cũ qua server mới. Khi tạo lại database bằng cách restore từ 1 bản backup thường báo lỗi không tìm thấy thư mục chứa database. Lúc này ta phải tạo sẵn một thư mục có đường dẫn giống với đường dẫn của thư mục chứa database bên server cũ.
Nếu ta muốn đặt database ở một thư mục khác thì thay vì sử dụng câu lệnh restore thông thường, sử dụng đoạn lệnh mẫu sau để chỉ định thư mục chứa database sau khi restore:
  1. USE master  
  2. GO  
  3. -- First determine the number and names of the files in the backup.  
  4. -- AdventureWorks2008R2_Backup is the name of the backup device.  
  5. RESTORE FILELISTONLY  
  6.    FROM AdventureWorks2008R2_Backup  
  7. -- Restore the files for MyAdvWorks.  
  8. RESTORE DATABASE MyAdvWorks -- có thể đổi tên mới ở chỗ này  
  9.    FROM AdventureWorks2008R2_Backup  
  10.    WITH RECOVERY,  
  11.    MOVE 'AdventureWorks2008R2_Data' TO 'D:\MyData\MyAdvWorks_Data.mdf',   
  12.    MOVE 'AdventureWorks2008R2_Log' TO 'F:\MyLog\MyAdvWorks_Log.ldf'  
  13. GO  
  14.       
Xem hướng dẫn chi tiết trên MSDN

Sử dụng Clipboard bằng javascript

Để đưa 1 giá trị text vào clipboard:
  1. window.clipboardData.setData('Text','aaaaaaaa');  
  2.       
Để lấy giá trị text đang lưu trong clipboard:
  1. var value = window.clipboardData.getData("Text");  
  2.       
Tuy nhiên để các hàm này hoạt động thì trình duyệt người dùng phải cho phép sử dụng clipboard. Hiện giờ đa số các trình duyệt đã disable tính năng này vì lý do an ninh hay 1 vài vấn đề khác:

Problems caused by unintended clipboard access

There are several types of problems which can happen if a website is able to use your system's clipboard through javascript:
  • A website may erase the clipboard data, which may cause you to lose important data that you had copied previously into the clipboard.
  • A website may change the clipboard data, which may cause different data to be pasted later on instead of the data you intended to paste originally.
  • A website may read the clipboard data, and use them in malicious ways or send them to a third party without your knowledge.
Therefore, you should only permit the websites that you absolutely trust to be able to access the clipboard.

Thứ Bảy, 28 tháng 7, 2012

Sử dụng Clipboard trong .NET

.NET cung cấp class Clipboard gồm các phương thức tĩnh để thao tác với Clipboard.

Ví dụ: Để đưa 1 đoạn text vào clipboard sử dụng:
  1. Clipboard.SetText("hanhtranglaptrinh.com");  
Kiểm tra bằng cách kiếm cái ô text nào đó Ctrl + V hoặc click phải chuột chọn paste sẽ thấy kết quả.

Để lấy 1 đoạn text đang được lưu trong clipboard ra sử dụng:
  1. string text = Clipboard.GetText();  
Kiểm tra bằng cách kiếm 1 đoạn văn bản nào đó bôi đen -> chuột phải chọn copy hoặc Ctrl + C sau đó chạy đoạn code trên và kiếm tra biến text.

Đối với ứng dụng windows (windows form, WPF, ... ) thì ngoài text ra còn có thể đưa một số object khác (Image, Stream, ...)  vào Clipboard. Ứng dụng silverlight chỉ hỗ trợ text.

Gửi Email bằng MS SQL Server

Sử dụng đoạn script sau để gửi email trong SQL Server:
  1. EXEC msdb.dbo.sp_send_dbmail  
  2. @profile_name ='Tên của cấu hình đã cài đặt để gửi mail',  
  3. @recipients=N'email người nhận',  
  4. @body=N'Nội dung email',  
  5. @subject = 'subject',  
  6. @body_format = 'HTML'  
  7.       
Note: Trước khi gửi email bạn phải cấu hình email trong SQL Server thì mới có thể gửi được email.

Thứ Sáu, 27 tháng 7, 2012

Dấu hỏi ? ngay sau kiểu dữ liệu có ý nghĩa gì trong C#

Đối với các kiểu dữ liệu không có giá trị null.
Ví dụ kiểu bool thì chỉ có 2 giá trị là true và false, kiểu int thì là những con số, ...
Khi bạn khai báo như sau sẽ bị báo lỗi:
  1. int a = null;  
  2. bool b = null;  
Hoặc:
  1. public int GetNull()  
  2. {  
  3.     return null;  
  4. }  
Hoặc khai báo hàm như sau:
  1. public static void XuLy(int a, int b)  
  2. { }  
Nhưng lúc truyền biến vào hàm là giá trị null:
  1. XuLy(1, null);  
Sử dụng dấu hỏi ? ngay sau kiểu dữ liệu ta được 1 kiểu dữ liệu mới. Miền giá trị bao gồm miền giá trị của kiểu dữ liệu cũ và thêm giá trị null nữa.
Khai báo như sau sẽ không còn báo lỗi nữa:
  1. int? a = null;  
  2. bool? b = null;  
  1. public int? GetNull()  
  2. {  
  3.     return null;  
  4. }  
  1. public static void XuLy(int a, int? b)  
  2. { }  
Note:
 - Chỉ có thể gán kiểu dữ liệu not null cho kiểu dữ liệu có thể null chứ ngược lại thì không.
 - Ví dụ có thể gán:
  1. int a = 5;  
  2. int? b = a;  
Chứ không thể gán:
  1. int? a = 5;  
  2. int b = a;  
Hoặc không thể:
  1. public int Test()  
  2. {  
  3.     return GetNull();  
  4. }  
  5. public int? GetNull()  
  6. {  
  7.     return null;  
  8. }  

Lấy thông tin các column và table từ INFORMATION_SCHEMA trong database Sql Server

Ngoài việc lấy thông tin các column và table từ sys.objects ta còn có thể xem thông tin các column và table trong INFORMATION_SCHEMA.

Xem thông tin các column trong database:
  1. select * from INFORMATION_SCHEMA.COLUMNS  
  2.       
Xem danh sách các table:
  1. select * from INFORMATION_SCHEMA.TABLES 
  2.       
Kết quả trả về bao gồm cả danh sách các View nữa. Nếu chỉ muốn lấy danh sách Table thôi thì filter theo TABLE_TYPE
  1. select * from INFORMATION_SCHEMA.TABLES where TABLE_TYPE ='BASE TABLE'  
  2.       
Ví dụ trong database mình có 1 table là tblBug.
Muốn xem danh sách các column của  tblBug:
  1. select TABLE_NAME, COLUMN_NAME, DATA_TYPE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='tblBug'  
  2.       

Hoặc tìm xem tất cả các Table nào có chứa column tên là DomainID:
  1. select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='DomainID'  
  2.       
Vậy là có thêm một cách nữa để xem nhanh danh sách các column và table trong database rồi. Sử dụng thông tin này để generate source code tự động nữa thì cũng tuyệt ^^!.

Thứ Năm, 26 tháng 7, 2012

Cách sử dụng ( đọc, thêm, sửa, xóa ) appSettings trong file app.config C#

Hiện giờ thường chỉ những file cấu hình đặc biệt người ta mới sử dụng file xml để cấu hình cho ứng dụng. Với những cấu hình không quá phức tạp thì việc sử dụng appSettings trong file app.config cực kỳ nhanh gọn.

Khai báo biến 'abc' có giá trị '01/01/1900 00:00:00 AM' trong appSettings  trong file app.config:
  1. <?xml version="1.0"?>  
  2. <configuration>  
  3. <startup>  
  4.   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>  
  5.   <appSettings>  
  6.     <add key="abc" value="01/01/1900 00:00:00 AM"/>  
  7.   </appSettings>  
  8. </configuration>  
  9.       
Để đọc giá trị của abc sử dụng:
  1. string abc = ConfigurationManager.AppSettings["abc"];  
  2.       
Khi cần thay đổi các giá trị cấu hình này, cách đơn giản nhất là mở file config lên và sửa ^^!. Tuy nhiên đối với những ứng dụng cho người dùng cuối, không thể bắt người dùng tự vào chỉnh sửa được mà ta phải làm chức năng cho họ cấu hình. Dưới đây là một số hàm cần thiết để chỉnh sửa file config.

- Sửa giá trị của biến trong appSettings trong file app.config:
  1. public static void EditAppSetting(string key, string value)  
  2. {  
  3.     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);  
  4.     config.AppSettings.Settings[key].Value = value;  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
- Thêm 1 giá trị mới vào appSettings trong file app.config:
  1. public static void AddAppSetting(string key, string value)  
  2. {  
  3.     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);  
  4.     config.AppSettings.Settings.Add(key,value);  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
- Xóa 1 giá trị ra khỏi appSettings trong file app.config:
  1. public static void RemoveAppSetting(string key)  
  2. {  
  3.     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);  
  4.     config.AppSettings.Settings.Remove(key);  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
Demo thử hàm edit nào:
  1. Console.WriteLine(ConfigurationManager.AppSettings["abc"]);  
  2. EditAppSetting("abc",DateTime.Now.ToString());  
  3. Console.WriteLine(ConfigurationManager.AppSettings["abc"]);  
  4. Console.ReadLine();  
Dòng đầu tiên sẽ in ra giá trị của abc trước khi sửa file config.
Dòng thứ 2 tiến hành sửa giá trị abc thành giá trị thời gian hiện tại trong file config.
Dòng thứ 3 tiến hành đọc lại và in ra giá trị của abc sau khi đã sửa file config.
Chạy lại thêm một lần nữa :
Vậy là xong. Sử dụng app.config nhanh hơn so với thao tác đọc và ghi file xml nhiều đúng không nào.

Note:
- Cần add Reference System.configuration.
- Sau khi chạy chương trình thì file config bị chỉnh sửa là file config trong cùng thư mục chứa file exe (có dạng TenUngDung.exe.config) chứ không phải file app.config trong project đâu nhé.
- Quá trình sửa file config chỉ chính xác khi build ứng dụng ra thành file exe và chạy. Nếu chạy trong chế độ debug thì bị tình trạng là đọc từ file TenUngDung.exe.config nhưng lại ghi ra file TenUngDung.vshost.exe.config.

Thứ Tư, 25 tháng 7, 2012

Sử dụng DataView để filter dữ liệu từ DataTable C#

Khi chúng ta được cung cấp 1 DataTable chứa dữ liệu nhưng chỉ cần lấy ra 1 số dòng thỏa điều kiện nào đó thôi. Cách truyền thống vấn là duyệt từng dòng rồi so sánh giá trị nếu phù hợp thì lấy, không phù hợp thì bỏ qua.
Sử dụng DataView để lấy dữ liệu theo điều kiện nào đó 1 cách nhanh chóng.

Demo:
Tạo 1 DataTable chứa thông tin tên và tuổi của một số người:
  1. DataTable table = new DataTable("table");  
  2. table.Columns.Add(new DataColumn("Name"typeof(string)));  
  3. table.Columns.Add(new DataColumn("Age"typeof(int)));  
  4. for (int i = 0; i < 5; i++)  
  5. {  
  6.     DataRow NewRow = table.NewRow();  
  7.     NewRow["Name"] = "Nguyễn Văn " + i;  
  8.     NewRow["Age"] = i;  
  9.     table.Rows.Add(NewRow);  
  10. }  
Bây giờ nếu chỉ muốn lấy những người có tuổi lớn hơn 2:
  1. // new 1 DataView  
  2. DataView dataView = new DataView(table);  
  3.   
  4. // chỉ lấy những người có tuổi lớn hơn 2  
  5. dataView.RowFilter = "Age > 2";  
Vậy là Ok, lúc này DataView chỉ chứa những dòng có giá trị thỏa điều kiện filter. Có thể dùng DataView này để đưa vào DataGridView.

Sử dụng 2 hàm sau để test kết quả:
  1. private static void PrintTable(DataTable table)  
  2. {  
  3.     for (int i = 0; i < table.Rows.Count; i++)  
  4.     {  
  5.         Console.WriteLine("\t" + table.Rows[i]["Name"] +": "+ table.Rows[i]["Age"] + " tuổi.");  
  6.     }  
  7.     Console.WriteLine();  
  8. }  
  9.   
  10. private static void PrintView(DataView view)  
  11. {  
  12.     for (int i = 0; i < view.Count; i++)  
  13.     {  
  14.         Console.WriteLine("\t" + view[i]["Name"] + ": " + view[i]["Age"] + " tuổi.");  
  15.     }  
  16.     Console.WriteLine();  
  17. }  
Thực hiện test:
  1. DataTable table = new DataTable("table");  
  2. table.Columns.Add(new DataColumn("Name"typeof(string)));  
  3. table.Columns.Add(new DataColumn("Age"typeof(int)));  
  4. for (int i = 0; i < 5; i++)  
  5. {  
  6.     DataRow NewRow = table.NewRow();  
  7.     NewRow["Name"] = "Nguyễn Văn " + i;  
  8.     NewRow["Age"] = i;  
  9.     table.Rows.Add(NewRow);  
  10. }  
  11.   
  12. // new 1 DataView  
  13. DataView dataView = new DataView(table);  
  14.   
  15. // chỉ lấy những người có tuổi lớn hơn 2  
  16. dataView.RowFilter = "Age > 2";  
  17.   
  18. PrintTable(table);  
  19. PrintView(dataView);  
  20. Console.ReadLine();  
Kết quả sau khi filter chỉ còn Nguyễn Văn 3 và Nguyễn Văn 4:

Thứ Ba, 24 tháng 7, 2012

Kiểm tra địa chỉ Ip V4 hợp lệ

Mình đang làm một chức năng mà người dùng sẽ nhập vào địa chỉ Ip.
Đoạn code đơn giản để kiểm tra xem một chuỗi có phải là địa chỉ Ip v4 hợp lệ hay không:
  1. public static bool IsIpV4Address(string str)  
  2. {  
  3.     string[] arr = str.Split('.');  
  4.     if (arr.Length != 4)  
  5.         return false;  
  6.     foreach (string sub in arr)  
  7.     {  
  8.         try  
  9.         {  
  10.             int test = int.Parse(sub);  
  11.             if (test < 0 || test > 255)  
  12.                 return false;  
  13.   
  14.             //nếu sub có nhiều chữ số 0 ở trước, khi convert qua số sẽ bị mất các số 0 ở đằng trước  
  15.             if (test.ToString().Length != sub.Length)  
  16.             {  
  17.                 // chứng tỏ sub có chứa các số 0 thừa ở đằng trước -> không hợp lệ.  
  18.                 return false;  
  19.             }  
  20.         }  
  21.         catch  
  22.         {  
  23.             return false;  
  24.         }  
  25.     }  
  26.     // vượt qua đc hết đống thử thách này thì chắc chắn là địa chỉ Ip V4 rùi ^^!    
  27.     return true;  
  28. }   

Thứ Hai, 23 tháng 7, 2012

Lấy danh sách tất cả các table, các column trong table và kiểu dữ liệu của column trong database Sql Server

Bài này mình sẽ hướng dẫn cách lấy danh sách tất cả các table, các column trong table và kiểu dữ liệu của column trong database Sql Server:

Lấy danh sách các table:
  1. select object_id,name from sys.objects where type='u'  
  2. -- hoặc  
  3. select object_id,name from sys.tables  
  4.       
Dựa vào object_id của mỗi table ta lấy ra được danh sách các column trong table đó:
  1. select * from sys.all_columns where object_id = [object_id của table]  
  2.       
Sau khi chạy câu truy vấn trên, để ý cột user_type_id nó chính là id của kiểu dữ liệu trong SQL. Truy vấn sys.types để lấy tên kiểu dữ liệu. Ví dụ kiểu bigint:
  1. select * from sys.types where user_type_id = 127  
  2.       
Lúc này ta đã lấy được kiểu dữ liệu của từng column trong table rồi đó.

Demo nào:
Trong database của mình có 1 table tên tblBug. Sau khi truy vấn mình lấy được object_id của nó là 248325189:
  1. select object_id,name from sys.objects where type='u' and name ='tblBug'  
  2.       
Lấy danh sách các column và kiểu dữ liệu:
  1. select cl.name as 'Tên column', tp.name as 'Kiểu dữ liệu',cl.max_length from sys.all_columns cl join sys.types tp on cl.user_type_id = tp.user_type_id where object_id = 248325189  
  2.       
Kết quả:
Lúc này có thể lấy các thông tin trên để generate source code tự động cho việc lập trình rùi.

Xem danh sách các object trong Database SQL Server

Truy vấn thông tin trong sys.objects để xem thông tin các object được tạo trong database. Những thông tin này rất có ích trong việc quản lý database.
  1. select * from sys.objects  
  2.       
Chúng ta có thể filter các object dựa vào type của chúng. Ví dụ bạn muốn lấy danh sách tất cả các table trong database:
  1. -- type='u' tức là table  
  2. select * from sys.objects where type='u'  
  3. -- tương đương với:  
  4. select * from sys.tables  
  5.       
Hoặc danh sách tất cả các stored procedure:
  1. select * from sys.objects where type='p'  
  2. -- tương đương với:  
  3. select * from sys.procedures  
  4.       
Danh sách type của các object tham khảo từ MSDN:
Object type:
AF = Aggregate function (CLR)
C = CHECK constraint
D = DEFAULT (constraint or stand-alone)
F = FOREIGN KEY constraint
FN = SQL scalar function
FS = Assembly (CLR) scalar-function
FT = Assembly (CLR) table-valued function
IF = SQL inline table-valued function
IT = Internal table
P = SQL Stored Procedure
PC = Assembly (CLR) stored-procedure
PG = Plan guide
PK = PRIMARY KEY constraint
R = Rule (old-style, stand-alone)
RF = Replication-filter-procedure
S = System base table
SN = Synonym
SO = Sequence object
SQ = Service queue
TA = Assembly (CLR) DML trigger
TF = SQL table-valued-function
TR = SQL DML trigger
TT = Table type
U = Table (user-defined)
UQ = UNIQUE constraint
V = View
X = Extended stored procedure
Nguồn MSDN

Toán tử ?? trong C#

Toán tử ?? được dùng để định nghĩa giá trị mặc định trả về nếu giá trị của biến là null.

Xem ví dụ sau:
  1. string input = "test@hanhtranglaptrinh.com";  
  2. string test = input;  
  3. test = test.Replace("@","[a còng]");  
  4. // giá trị của test lúc này là: test[a còng]hanhtranglaptrinh.com  
Chuyện gì sẽ xảy ra nếu gán giá trị input bằng null.
  1. string input = null;  
  2. string test = input;  
  3. test = test.Replace("@","[a còng]");  
  4. // sẽ có exception khi gọi phương thức replace vì lúc này biến test cũng bằng null
Sử dụng toán tử ?? để gắn giá trị mặc định cho biến test khi biến input bằng null. Lúc này biến test sẽ được gắn giá trị mặc định nên đoạn code vẫn chạy bình thường.
  1. string input = null;  
  2. string test = input ?? "giá trị mặc định";  
  3. test = test.Replace("@","[a còng]");  
Đoạn code trên tương đương với:
  1. string input = null;  
  2. string test;  
  3. if (input == null)  
  4.     test = "giá trị mặc định";  
  5. else  
  6.     test = input;  
  7. test = test.Replace("@""[a còng]");  
Hoặc tương đương với cách sử dụng toán tử ?: như sau:
  1. string input = null;  
  2. string test = (input == null) ? "giá trị mặc định" : input;  
  3. test = test.Replace("@""[a còng]");  
Xem thêm: Toán tử ?: trong C#

Chủ Nhật, 22 tháng 7, 2012

Tìm kiếm trong danh sách hoặc mảng sử dụng LINQ query

Biết cách sử dụng LINQ query là một lợi thế lớn trong lập trình .NET, sử dụng nhanh chóng, cách viết câu query khá giống và quen thuộc với cách viết T-SQL.

Tìm kiếm trong danh sách:
  1. List<int> list = new List<int>();  
  2. list.Add(1);  
  3. list.Add(2);  
  4. list.Add(2);  
  5. list.Add(3);  
  6. list.Add(4);  
  7. list.Add(5);  
  8.   
  9. // lấy ra trong danh sách những phần tử >2  
  10. List<int> result = (from item in list where item > 2 select item).ToList();  
  11.   
  12. // lấy giá trị đầu tiên  
  13. int first = (from item in list where item > 2 select item).First();  
Tìm kiếm trong mảng:
  1. int[] arr = new int[] { 1, 2, 2, 3, 4, 5 };  
  2.   
  3. // lấy ra trong danh sách những phần tử >2  
  4. int[] result = (from item in arr where item > 2 select item).ToArray();  
  5.   
  6. // lấy giá trị đầu tiên  
  7. int first = (from item in arr where item > 2 select item).First();  
Một ví dụ sử dụng class:
  1. class Person  
  2. {  
  3.     public string Name { getset; }  
  4.     public int Age { getset; }  
  5.   
  6.     public Person(string name, int age)  
  7.     {  
  8.         Name = name;  
  9.         Age = age;  
  10.     }  
  11. }  
  1. List<Person> list = new List<Person>();  
  2. list.Add(new Person("Nguyễn Văn A",16));  
  3. list.Add(new Person("Nguyễn Văn B", 17));  
  4. list.Add(new Person("Nguyễn Văn C", 18));  
  5.   
  6. // tìm tuổi của Nguyễn Văn A  
  7. int age = (from person in list where person.Name == "Nguyễn Văn A" select person).First().Age;  
Chú ý: toán sử so sánh bằng vẫn là 2 dấu bằng '==' chứ không phải 1 dấu bằng như trong SQL đâu nhé.

Thứ Tư, 18 tháng 7, 2012

Toán tử ? : trong C#

Cái này lúc đầu thấy hơi khó sử dụng nhưng sử dụng nhiều thấy cũng hay và code ngắn gọn:
Cú pháp: điều kiện ? giá trị trả về nếu thỏa điều kiện : giá trị trả về nếu không thỏa điều kiện
Ví dụ:
  1. int i = 5;  
  2. string test = i < 0 ? "i bé hơn 0" : "i lớn hơn 0";  
Đoạn code trên tương đương với:
  1. int i = 5;  
  2. string test;  
  3. if (i < 0)  
  4. {  
  5.     test = "i bé hơn 0";  
  6. }  
  7. else  
  8. {  
  9.     test = "i lớn hơn 0";  
  10. }  
Có thể sử dụng kết hợp:
  1. int i = -5;  
  2. string test = i < 0 ? "i bé hơn 0" + (i < -1 ? " và i bé hơn -1" : "") : "i lớn hơn 0";  
Nguồn:MSDN

Thứ Hai, 16 tháng 7, 2012

Sử dụng phương thức TryParse khi convert object

Khi muốn convert 1 object nguồn thành 1 object đích ta thường sử dụng các phương thức tĩnh Parse hoặc TryParse có sẵn của object đích để convert object nguồn thành object đích.
 - Sử dụng phương thức Parse. Nếu object nguồn không đúng định dạng và không thể convert được thành object đích thì sẽ throw exception lên. Để tránh lỗi và biết được có convert thành công hay không chúng ta cần phải sử dụng try catch.
 - Sử dụng phương thức TryParse sẽ trả về object kết quả, đồng thời báo cho ta biết có convert thành công hay không. Nếu object nguồn không đúng định dạng và không thể convert được thành object đích thì sẽ trả về kết quả không thành công.
- Cách sử dụng TryParse:
  1. DateTime dateTime;  
  2. if (DateTime.TryParse("abc"out dateTime))  
  3. {  
  4.     // thành công, biến dateTime đã có thể sử dụng được 
  5. }  
  6. else  
  7. {  
  8.     // thất bại  
  9. }  
- Đoạn code trên tương đương với:
  1. DateTime dateTime;  
  2. try  
  3. {  
  4.     dateTime = DateTime.Parse("abc");  
  5. }  
  6. catch  
  7. {  
  8.   
  9. }  
- Tùy từng trường hợp xử lý khác nhau mà có thể áp dụng các cách làm khác nhau. Nhưng nếu chỉ muốn kiểm tra dữ liệu có hợp lệ hay không để quyết định các bước xử lý tiếp theo thì sử dụng TryParse là một lợi thế, code sẽ ngắn gọn và dễ hiểu hơn nhiều.

Ghi thêm dữ liệu vào cuối file đã tồn tại

Khi khai báo 1 StreamWrite để ghi file sử dụng StreamWriter(string path, bool append) hoặc File.AppendText(string path) để cho biết rằng nếu file đã tồn tại thì dữ liệu sẽ được ghi tiếp vào cuối file chứ không chép đè lên file cũ. Nếu file chưa tồn tại sẽ tạo file mới.

Demo:
  1. // cách 1  
  2. using (StreamWriter sw = new StreamWriter("abc.txt"true))  
  3. {  
  4.     sw.WriteLine(DateTime.Now.ToString() + Environment.NewLine);  
  5. }  
  6.   
  7. // cách 2  
  8. using (StreamWriter sw = File.AppendText("abc.txt"))  
  9. {  
  10.     sw.WriteLine(DateTime.Now.ToString() + Environment.NewLine);  
  11. }  

Chủ Nhật, 15 tháng 7, 2012

Ký tự xuống dòng ( new line character ) trong MS SQL

Sử dụng char(10) hoặc char(13) để trả về ký tự xuống dòng.
Ví dụ:
  1. select 'abc' + char(10) +'def'  
  2.   
  3. select 'abc' + char(13) +'def'  
  4.       
Test:
  1. string test1 = connTest.ExecuteScalar("select 'abc' + char(10) +'def'").ToString();  
  2. string test2 = connTest.ExecuteScalar("select 'abc' + char(13) +'def'").ToString();  
Kết quả:
test1 = "abc\ndef" và test2 = "abc\rdef"

Thứ Hai, 2 tháng 7, 2012

Tổng hợp các hàm xử lý chuỗi trong MS SQL Server

Mình làm một bài viết về danh sách các hàm hệ thống xử lý chuỗi trong SQL. Danh sách các hàm xử lý này mọi người có thể tìm trên MSDN hoặc trong phần System Functions trong mỗi database SQL.

1. Hàm Ascii

  1. -- 1. Ascii  
  2. -- trả về mã ascii của ký tự  
  3. select ascii('A')  
  4. -- kết quả: 65      
2. Hàm Char
  1. -- 2. Char   
  2. -- trả về ký tự của mã ASCII  
  3. select char(65)  
  4. -- kết quả: A    
3. Hàm charindex
  1. -- 3. charindex  
  2. -- trả về vị trí xuất hiện của 1 chuỗi con trong 1 chuỗi bắt đầu từ 1 vị trí xác định  
  3. select charindex('abc','cabcaaaa',2)  
  4. -- giải thích: từ vị trí số 2 của chuỗi 'cabcaaaa' tức là từ ký tự 'a' trở đi tìm vị trí xuất hiện của chuỗi 'abc'  
  5. -- kết quả là chuỗi 'abc' xuất hiện ở vị trí ký tự thứ 2 của chuỗi 'cabcaaaa'       
4. Hàm Left
  1. -- 4. left  
  2. -- lấy ra n ký tự đầu tiên của chuỗi.  
  3. select left('123456',3)  
  4. -- ví dụ: lấy ra 3 ký tự đầu tiên của chuỗi '123456'  
  5. -- kết quả: '123'       
5. Hàm Right
  1. -- 5. right  
  2. -- lấy ra n ký tự cuối cùng của chuỗi  
  3. -- ví dụ: lấy ra 3 ký tự cuối cùng của chuỗi '123456'  
  4. select right('123456',3)  
  5. -- kết quả: '456'  
6. Hàm Len
  1. -- 6. len()  
  2. -- trả về số lượng ký tự hay độ dài của chuỗi  
  3. select len('abcd')  
  4. -- kết quả: 4    
7. Hàm Lower
  1. -- 7. lower  
  2. -- viết thường tất cả các ký tự  
  3. select lower('aaBBcCdGG')  
  4. -- kết quả: aabbccdgg    
8. Hàm Upper
  1. -- 8. upper  
  2. -- viết hoa tất cả các ký tự  
  3. select upper('aaBBcCdGG')  
  4. -- kết quả: AABBCCDGG       
9. Hàm LTrim
  1. -- 9. Ltrim  
  2. -- Xóa tất cả các ký tự rỗng, khoảng trắng ở ĐẦU chuỗi.  
  3. select Ltrim('     abc     ')  
  4. -- kết quả: 'abc     '       
10. Hàm RTrim
  1. -- 10. Rtrim  
  2. -- Xóa tất cả các ký tự rỗng, khoảng trắng ở CUỐI chuỗi.  
  3. select Rtrim('     abc     ')  
  4. -- kết quả: '     abc'    
11. Hàm PatIndex
  1. -- 11. patindex  
  2. -- trả về vị trí xuất hiện của 1 mẫu trong 1 chuỗi  
  3. SELECT PATINDEX('%ensure%''please ensure the door is locked');  
  4. -- kết quả: 8  
  5. -- note: sử dụng ký tự _ để thay thế cho 1 ký tự bất kỳ  
  6. SELECT PATINDEX('%en_ure%''please ensure the door is locked');  
  7. -- kết quả vẫn là: 8  
12. Hàm Quote
  1. -- 12. quotename  
  2. -- trích dẫn  
  3. select quotename('hanh trang lap trinh dot com')  
  4. -- kết quả: [hanh trang lap trinh dot com]  
  5. -- có thể đổi ký tự trích dẫn khác như :ngoặc đơn ( hay dấu nháy '  
  6. select quotename('hanh trang lap trinh dot com',')')  
  7. -- kết quả: (hanh trang lap trinh dot com)  
13. Hàm Replace
  1. -- 13. replace  
  2. -- thay thế tất cả các chuỗi con nào đó trong 1 chuỗi thành 1 chuỗi con khác  
  3. select replace('hanh trang lap trinh dot com accom','com','net')  
  4. -- Tất cả các từ 'com' trong chuỗi sẽ được thay bằng từ 'net'  
  5. -- Kết quả: hanh trang lap trinh dot net acnet  
14. Hàm replicate
  1. -- 14. replicate  
  2. -- nhân 1 chuỗi lên nhiều lần  
  3. select replicate('acb',5)  
  4. -- chuỗi 'acb' được lặp lại 5 lần.  
  5. -- kết quả: acbacbacbacbacb    
15. Hàm Reverse
  1. -- 15. reverse  
  2. -- quay ngược chuỗi lại  
  3. select reverse('abcdef')  
  4. -- kết quả: fedcba  
16. Hàm Space
  1. -- 16. space  
  2. -- trả về 1 chuỗi gồm n ký tự khoảng trắng.  
  3. select 'a' +space(54) +'b'  
  4. -- kết quả: 'a                                                      b'  
  5. -- ký tự a + 54 ký tự khoảng trắng + ký tự b  
17. Hàm Str
  1. -- 17. Str  
  2. -- chuyển một số thành một chuỗi. Hàm này rắc rối, mình chưa biết ích lợi để làm gì nữa.  
  3. select str(5.333333,20,2)  
  4. -- giải thích: chuyển số 5.333333 thành chuỗi có độ dài là 20 ký tự, chỉ lấy 2 ký tự thập phân sau dấu '.'  
  5. -- nếu số trên khi chuyển thành chuỗi mà chưa đủ 20 ký tự thì sẽ tự thêm các khoảng trắng vào phía trước sao cho đủ 20 ký tự.  
  6. -- kết quả: '                5.33'  
  7.   
  8. -- nếu số lượng chữ số phần nguyên của số mà nhiều hơn độ dài chuỗi trả về thì sẽ trả về các giá trị là ký tự '*'  
  9. select str(5555.333333,3,2)  
  10. -- kết quả trả về là 3 ký tự '*' : '***' vì độ dài chuỗi trả về là 3 trong khi số lượng chữ số phần nguyên là 4.  
18. Hàm Stuff
  1. -- 18. stuff  
  2. -- hàm này sẽ thay thế n ký tự bắt đầu từ 1 vị trí xác định bằng 1 chuỗi muốn thay vào  
  3. SELECT STUFF('abcdef', 2, 3, 'ijklmn');  
  4. -- giải thích: từ vị trí 2 tức là ký tự 'b' lấy ra 3 ký tự -> 'bcd' và thay thế bằng 'ijklmn'   
  5. -- kết quả: aijklmnef   
19. Hàm Substring
  1. -- 19. substring  
  2. -- cắt ra 1 chuỗi nhỏ từ chuỗi ban đầu  
  3. select substring('abcdefgh',2,5)  
  4. -- giải thích: từ vị trí thứ 2 lấy ra 5 ký tự liên tiếp  
  5. -- kết quả: bcdef  
20. Hàm Unicode
  1. -- 20. unicode  
  2. -- trả về giá trị unicode của ký tự đầu tiên của chuỗi  
  3. select unicode(N'Áac')  
  4. -- kết quả: 193  
21. Hàm NChar
  1. -- 21. Nchar  
  2. -- trả về ký tự unicode của mã unicode  
  3. select Nchar( unicode(N'Áac'))  
  4. select Nchar( 193)  
  5. -- kết quả cả 2 câu truy vấn đề là : Á    
22. Hàm Soundex
  1. -- 22. soundex  
  2. -- Soundex là một thuật toán ngữ âm để liệt kê các từ theo âm sắc, theo cách phát âm của tiếng Anh. Mục đích là mã hóa những từ có cùng cách phát âm qua những đặc trưng giống nhau, từ đó người ta có thể tìm được một từ nào đó dù có sai sót nhỏ trong chính tả từ đó  
  3. select soundex('Brothers')  
  4. -- kết quả là 1 chuỗi gồm 4 ký tự: B636. Ký tự đầu tiên của kết quả cũng chính là ký tự đầu tiên của chuỗi ban đầu  
23. Hàm Difference
  1. -- 23. difference  
  2. -- hàm trả về số lượng ký tự giống nhau của 2 chuỗi sau khi đã mã hóa soundex. Giá trị kết quả nằm trong khoảng từ 0 đến 4  
  3. select difference('Brothers','Brothers')  

Chủ Nhật, 1 tháng 7, 2012

Cộng chuỗi với số trong MS Sql ?

Hi như chúng ta đã quen với việc lập trình C# khi cộng 1 chuỗi với 1 số thì kết quả trả về sẽ là một chuỗi. Hôm nay ngồi viết câu truy vấn dưới sql thì phát hiện 1 điều ngược lại.
Khi select 1 chuỗi + với 1 số sql sẽ cố convert qua kiểu số. Nếu chuỗi không thể convert được qua kiểu số thì câu truy vấn sẽ báo lỗi.

Ví dụ trên C#:
  1. object o1 = "0111" + 5;  
  2. // kết quả sẽ là "01115"  
  3.   
  4. object o2 = "0111aa" + 5;  
  5. // kết quả sẽ là "0111aa5"  
Trong Sql:
  1. select '0111' + 5  
  2. -- kết quả 116  
  3.  
  4. select '0111aa' + 5  
  5. -- báo lỗi: Conversion failed when converting the varchar value '0111aa' to data type int
Nếu muốn truy vấn thành công bắt buộc phải ép số về chuỗi.

  1. select '0111aa' + cast(5 as varchar)  
  2. -- kết quả: 0111aa5  

Tự động điền dữ liệu vào texbox và click vào button trong webbrowser control C#

Hôm nay làm cái tool lấy dữ liệu tự động từ 1 trang web. Công việc cần làm là điền dữ liệu input vào 1 textbox sau đó bấm vào button để lấy kết quả trả về. Mình sử dụng webbrowser control giả lập người dùng điền dữ liệu và bấm vào nút lấy kết quả. Sẵn tiện chia sẻ với mọi người cách làm, có thể sử dụng để làm chức năng đăng nhập, post bài tự động.

Để điền dữ liệu vào textbox ta làm như sau:
  1. private void SetText(string elementId, WebBrowser webbrowser, string text)  
  2. {  
  3.     HtmlElement element = webbrowser.Document.GetElementById(elementId);  
  4.     element.InnerText = text;  
  5. }  
Để click vào button sử dụng hàm sau:
  1. private void InvokeClick(string elementId,WebBrowser webbrowser)  
  2. {  
  3.     HtmlElement element = webbrowser.Document.GetElementById(elementId);  
  4.     element.InvokeMember("click");  
  5. }  
Trong đó elementId chính là giá trị của attribute id của thẻ html. Làm sao để có giá trị này thì có thể sử dụng chức năng inspect element của chrome hay các addon của firefox để tìm ^^!.

Mình làm 1 ví dụ về chức năng tự động đăng nhập vào 1 trang web như sau:
- Đầu tiên tìm id của thẻ html nhập username. Ở đây mình giả sử là: txtUserName.
- Tìm id của thẻ html nhập password. Ở đây mình giả sử là txtPassword.
- Tìm id của button đăng nhập. Ở đây mình giả sử là btnLogin.
  1. // chuyển đến trang đăng nhập  
  2. webBrowser1.Navigate("http://hanhtranglaptrinh.com/login.aspx");  
  3. int timeOut = 5;  
  4. DateTime start = DateTime.Now;  
  5. DateTime now = DateTime.Now;  
  6. // đợi load xong trang  
  7. while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)  
  8. {  
  9.     Application.DoEvents();  
  10.     now = DateTime.Now;  
  11.     if ((now - start).TotalMinutes >= timeOut)  
  12.     {  
  13.         // làm cái gì đó  
  14.         throw new Exception("time out");  
  15.     }  
  16. }  
  17. // điền username  
  18. SetText("txtUserName", webBrowser1, "admin");  
  19. // điền pass  
  20. SetText("txtPassword",webBrowser1,"123");  
  21. // nhấn nút đăng nhập  
  22. InvokeClick("btnLogin", webBrowser1);  
Trường hợp trên là đối với các thẻ html có attribute id nên ta sẽ dễ dàng tìm ra đúng thẻ để điền dữ liệu và click vì attribute id là duy nhất. Đối với trường hợp các thẻ html không có attribute id có thể sử dụng các attribute khác như: name, class ... Tuy nhiên các attribute có thể không duy nhất nên sẽ tìm không đúng thẻ html để điền dữ liệu hay click. Ở bài sau mình sẽ hướng dẫn tìm ra thẻ html với các attribute khác.