Chuyển chuổi thành chữ hoa đầu (title case)

Đơn giản vậy thôi

using System.Globalization;

String myString = "HI, I AM GENESIO";

String myTitleCaseString = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(myString.ToLower());

Chạy ASP net không cần ISS(máy cài Net framawwork hoặc VS2k8)

máy đã cài VS2k8 thì cop cái này lưu lại thành file *.bat

@echo off
SET LocalProgramFiles="%ProgramFiles(x86)%"
IF %LocalProgramFiles% == "" SET LocalProgramFiles="%ProgramFiles%"
set currentdir=%cd%
pushd "%LocalProgramFiles%\Common Files\microsoft shared\DevServer\9.0\"
start WebDev.WebServer.EXE /port:6519 /path:"%currentdir%"
start http://localhost:6519/

Một số khái niệm về mô hình 3 lớp (3 layers) – n-tiers , 3-tiers, multi tiers

Trong bài viết này không có tham vọng trình bày lại chi tiết mô hình thiết kế ứng dụng đa lớp/tầng là như thế nào. Chỉ tóm tắt ngắn gọn lại những điểm chính của mô hình 3 lớp, mà cụ thể là 3 lớp logic.

Lưu ý: Các bạn không nên nhầm lẫn khái niệm lớp(layer) trong phần này với khái niệm lớp(class) của các ngôn ngữ lập trình hướng đối tượng.

Trong phát triển ứng dụng, để dễ quản lý các thành phần của hệ thống, cũng như không bị ảnh hưởng bởi các thay đổi, người ta hay nhóm các thành phần có cùng chức năng lại với nhau và phân chia trách nhiệm cho từng nhóm để công việc không bị chồng chéo và ảnh hưởng lẫn nhau. Ví dụ trong một công ty bạn có từng phòng ban, mỗi phòng ban sẽ chịu trách nhiệm một công việc cụ thể nào đó, phòng này không được can thiệp vào công việc nội bộ của phòng kia như Phòng tài chính thì chỉ phát lương, còn chuyện lấy tiền đâu phát cho các anh phòng Marketing thì các anh không cần biết. Trong phát triển phần mềm, người ta cũng áp dụng cách phân chia chức năng này. Bạn sẽ nghe nói đến thuật ngữ kiến trúc đa tầng/nhiều lớp, mỗi lớp sẽ thực hiện một chức năng nào đó, trong đó mô hình 3 lớp là phổ biến nhất. 3 lớp này là gì? Là Presentation, Business Logic, và Data Access. Các lớp này sẽ giao tiếp với nhau thông qua các dịch vụ(services) mà mỗi lớp cung cấp để tạo nên ứng dụng, lớp này cũng không cần biết bên trong lớp kia làm gì mà chỉ cần biết lớp kia cung cấp dịch vụ gì cho mình và sử dụng nó mà thôi.
Mô hình 3 lớp mà Microsoft đề nghị dùng cho các hệ thống phát triển trên nền .NET như sau:
Bạn có thể tham khảo chi tiết các đề nghị thiết kế các thành phần trong lớp này như thế nào ở đây:

http://www.microsoft.com/Downloads/details.aspx?familyid=A08E4A09-7AE3-4942-B466-CC778A3BAB34&displaylang=en

Presentation Layer

Lớp này làm nhiệm vụ giao tiếp với người dùng cuối để thu thập dữ liệu và hiển thị kết quả/dữ liệu thông qua các thành phần trong giao diện người sử dụng. Lớp này sẽ sử dụng các dịch vụ do lớp Business Logic cung cấp. Trong .NET thì bạn có thể dùng Windows Forms, ASP.NET hay Mobile Forms để hiện thực lớp này.
Trong lớp này có 2 thành phần chính là User Interface Components và User Interface Process Components.
UI Components là những phần tử chịu trách nhiệm thu thập và hiển thị thông tin cho người dùng cuối. Trong ASP.NET thì những thành phần này có thể là các TextBox, các Button, DataGrid…

UI Process Components: là thành phần chịu trách nhiệm quản lý các qui trình chuyển đổi giữa các UI Components. Ví dụ chịu trách nhiệm quản lý các màn hình nhập dữ liệu trong một loạt các thao tác định trước như các bước trong một Wizard…
Lưu ý : lớp này không nên sử dụng trực tiếp các dịch vụ của lớp Data Access mà nên sử dụng thông qua các dịch vụ của lớp Business Logic vì khi bạn sử dụng trực tiếp như vậy, bạn có thể bỏ qua các ràng buộc, các logic nghiệp vụ mà ứng dụng cần phải có.
Business Logic Layer

Lớp này thực hiện các nghiệp vụ chính của hệ thống, sử dụng các dịch vụ do lớp Data Access cung cấp, và cung cấp các dịch vụ cho lớp Presentation. Lớp này cũng có thể sử dụng các dịch vụ của các nhà cung cấp thứ 3 (3rd parties) để thực hiện công việc của mình(ví dụ như sử dụng dịch vụ của các cổng thanh tóan trực tuyến như VeriSign, Paypal…).
Trong lớp này có các thành phần chính là Business Components, Business Entities và Service Interface.
Service Interface là giao diện lập trình mà lớp này cung cấp cho lớp Presentation sử dụng. Lớp Presentation chỉ cần biết các dịch vụ thông qua giao diện này mà không cần phải quan tâm đến bên trong lớp này được hiện thực như thế nào.

Business Entities là những thực thể mô tả những đối tượng thông tin mà hệ thống xử lý. Trong ứng dụng chúng ta các đối tượng này là các chuyên mục(Category) và bản tin(News). Các business entities này cũng được dùng để trao đổi thông tin giữa lớp Presentation và lớp Data Access.

Business Components là những thành phần chính thực hiện các dịch vụ mà Service Interface cung cấp, chịu trách nhiệm kiểm tra các ràng buộc logic(constraints), các qui tắc nghiệp vụ(business rules), sử dụng các dịch vụ bên ngoài khác để thực hiện các yêu cầu của ứng dụng.
Trong ứng dụng của chúng ta, lớp này sẽ chứa các thành phần là CategoryService và NewsService làm nhiệm vụ cung cấp các dịch vụ quản lý chuyên mục và các bản tin (thêm, xóa, sửa, xem chi tiết, lấy danh sách…).
Data Access Layer

Lớp này thực hiện các nghiệp vụ liên quan đến lưu trữ và truy xuất dữ liệu của ứng dụng. Thường lớp này sẽ sử dụng các dịch vụ của các hệ quản trị cơ sở dữ liệu như SQL Server, Oracle,… để thực hiện nhiệm vụ của mình. Trong lớp này có các thành phần chính là Data Access Logic, Data Sources, Servive Agents).
Data Access Logic components (DALC) là thành phần chính chịu trách nhiệm lưu trữ vào và truy xuất dữ liệu từ các nguồn dữ liệu – Data Sources như RDMBS, XML, File systems…. Trong .NET Các DALC này thường được hiện thực bằng cách sử dụng thư viện ADO.NET để giao tiếp với các hệ cơ sở dữ liệu hoặc sử dụng các O/R Mapping Frameworks để thực hiện việc ánh xạ các đối tượng trong bộ nhớ thành dữ liệu lưu trữ trong CSDL. Chúng ta sẽ tìm hiểu các thư viện O/R Mapping này trong một bài viết khác.

Service Agents là những thành phần trợ giúp việc truy xuất các dịch vụ bên ngòai một cách dễ dàng và đơn giản như truy xuất các dịch vụ nội tại.
Chúng ta đã tìm hiểu qua các lớp của mô hình 3 lớp. Lý thuyết hơi nhiều một chút có thể làm bạn khó hiểu vì khả năng trình bày có hạn, nên bây giờ thử tìm hiểu một qui trình cụ thể hơn để biết các lớp này giao tiếp với nhau như thế nào. Ví dụ trong ứng dụng của chúng ta có thao tác tạo một chuyên mục mới, thì các lớp sẽ ltương tác với nhau như sau:
Lớp Presentation
- Trình bày một web form, có các text box cho phép người sử dụng nhập tên và mô tả cho chuyên mục
- Khi người dùng nhấn nút tạo trên form này, ứng dụng sẽ thực hiện việc tạo một Business Entity Category mới như đoạn code sau minh họa:

public void CreateNewCategory()
{
Category category = new Category();
category.Name = name.Text;
category.Description = description.Text;
// sử dụng dịch vụ do lớp Business cung cấp để tạo chuyên mục
CategoryService.CreateCategory(category);
}
Lớp Business Logic
Để cung cấp dịch vụ tạo một chuyên mục, thành phần CategoryService sẽ cung cấp hàm sau:
[sourcecode language='c#']
public static void CreateCategory(Category category)
{
// kiểm tra xem tên khóa của chuyên mục đã tồn tại chưa?
…
// kiểm tra tên khóa của chuyên mục có hợp lệ không?
…
// sử dụng DV của lớp Data Access để lưu chuyên mục mới này vào CSDL
CategoryDAO categoryDAO = new CategoryDAO();
categoryDAO.CreateCategory(category);
}
Lớp Data Access
Tương tự, để cung cấp dịch vụ lưu một chuyên mục mới vào CSDL, thành phần CategoryDAO sẽ cung cấp hàm sau (sử dụng ADO.NET để kết nối với CSDL):
[sourcecode language='c#']
public void CreateCategory(Category category)
{
// tạo connection
…
// tạo command, khởi tạo các tham số…
command.Parameters.Add(new SqlParameter(“@KeyName”, category.KeyName));
command.Parameters.Add(new SqlParameter(“@Name”, category.Name));
command.Parameters.Add(new SqlParameter(“@Description”, category.Description));
// lưu dữ liệu
command.ExecuteNonQuery();
}

Phân tích và thiết kế

Ứng dụng của chúng ta sẽ viết bằng ASP.NET 2.0 và SQL Server 2000/2005. Ngôn ngữ được dùng là C#.
Chúng ta đã tìm hiểu qua các thành phần chính trong mô hình 3 lớp, giờ đến lúc bắt tay vào thiết kế các thành phần đó cho ứng dụng tin tức của chúng ta. Trong ứng dụng tin tức mà chúng ta đã tìm hiểu yêu cầu qua bài viết trước, chúng ta thấy có hai đối tượng thông tin chính mà chúng ta cần quản lý là các chuyên mục(category) và tin tức(news). Ứng dụng quản lý của chúng ta sẽ thu thập những đối tượng dữ liệu này từ người dùng(phóng viên, biên tập viên) và trình bày lại cho người sử dụng khác xem(độc giả). Giờ chúng ta bắt tay vào thiết kế các thành phần Business Entities.
Business Entities

Ứng dụng của chúng ta sẽ bao gồm 2 entity chính là Category và News.
Trước hết là Category. Một chuyên mục (Category) sẽ gồm những thông tin sau:
CategoryId: Mã chuyên mục – sẽ được sinh tự động khi tạo mới
Name: Tên chuyên mục. VD: Vi tính, Kinh tế…
KeyName: Tên gợi nhớ dùng để phân biệt chuyên mục với nhau (không được trùng nhau). VD với VNExpress bạn sẽ thấy có Vi-tinh, Suc-khoe…
Description: Mô tả cho chuyên mục. VD: Description cho Vi-tinh là: thông tin mới nhất về công nghệ thông tin của Việt Nam và thế giới…
Picture: Hình ảnh đại diện cho chuyên mục
Trong ứng dụng đơn giản này, chúng ta chỉ thiết kế chuyên mục có một cấp, không có các chuyên mục con, cháu… Và ứng dụng này cũng không có phần quản lý các nhà biên tập viên, nhà báo và cơ chế cấp quyền hạn duyệt bài, gửi bài…Tôi dành phần này cho các bạn phát triển thêm, nhưng tôi cũng sẽ gợi ý cho các bạn cách thiết kế trong phần mở rộng ứng dụng.
Tiếp theo là News. Mỗi một bản tin sẽ có các thông tin sau:
NewsId: mã bản tin. Sẽ được sinh tự động khi tạo mới.
Title: tiêu đề chính của bản tin. VD: Microsoft tuyên bố phá sản!
Subtitle: tiêu đề phụ của bản tin. VD: Bill Gates từ chức!
Excerpt: phần giới thiệu ngắn gọn của bản tin
Authors: danh sách tác giả bản tin. VD: Nguyễn Văn A, Hoàng Thị B
Keywords: danh sách từ khóa chính trong bản tin dùng để tìm kiếm. VD: Microsoft, broken
Body: Đây là phần nội dung chính của bản tin.
Picture: Hình ảnh minh họa cho bản tin.
CreationTime: Ngày giờ tạo bản tin
LastModificationTime: Ngày giờ chỉnh sửa cuối cùng của bản tin
PublishedTime: Ngày giờ bản tin được đăng
TotalViews: Tổng số lượt người xem bản tin
TotalRates: Tổng số lượt người đánh giá bản tin
Rate: Điểm đánh giá trung bình của bản tin
Status: Trạng thái hiện tại của bản tin. Có thể là Writting(Đang viết), Approving(Đang chờ duyệt), Published(Đã được đăng)
Business Service Components

Bước tiếp theo chúng ta sẽ phân tích và thiết kế các Business Service Components. Các thành phần này sẽ làm nhiệm vụ chính cung cấp các dịch vụ cho lớp Presentation dùng để lấy và lưu trữ thông tin.
Lớp CategoryService
Chúng ta cần những thao tách chính trên đối tượng dữ liệu Category:
Tạo mới – CreateCategory(Category category)
Cập nhật – UpdateCategory(Category category)
Xóa – DeleteCategory(int categoryId)
Lấy thông tin chi tiết – GetCategory(int categoryId)
Lấy danh sách các category – GetCategories()
Kiểm tra một Key xem có trong database chưa – CheckKey(string keyName). Thao tác này dùng để kiểm tra xem khi tạo mới một category thì KeyName đã tồn tại trong hệ thống chưa. Thao tác này có thể dùng trên lớp Presentation để kiểm tra và thông báo lỗi cho người dùng khi họ nhập một tên khóa đã có trong hệ thống
Lưu ý: Chúng ta sẽ thực hiện các business logic của hệ thống trong lớp này.
Tương tự đối với lớp NewsService, dựa trên những gì yêu cầu chúng ta phân tích ở bài viết đầu tiên, chúng ta cần những thao tác chính sau đây trên đối tượng News:
Tạo mới – CreateNews(News news)
Cập nhật – UpdateNews(News news)
Xóa – DeleteNews(int newsId)
Lấy thông tin chi tiết – GetNews(int newsId)
Lấy danh sách các bản tin thuộc một chuyên mục nào đó, sắp xếp theo tin mới nhất – GetNewsOfCategory(int categoryId, int page, int pageSize, out int totalRecords)
Cập nhật số lần xem của một bản tin – UpdateTotalViews(int newsId)
Cập nhật đánh giá cho một bản tin – UpdateRate(int newsId, int rate)
Tìm bài viết dựa trên từ khóa – SearchNews(string keyWords, int page, int pageSize, out int totalRecords)
Trong các hàm trên, các bạn chú ý đến hàm GetNewsOfCategory. Trong hàm này có các tham số dùng để phân trang các bản tin. Chúng ta cần đến chức năng này vì khi trình bày trên trang tin, chúng ta chỉ trình bày một số lượng có hạn các bản tin của một chuyên mục nào đó chứ không thể trình bày tất cả trên màn hình được. Khi người dùng muốn xem thêm, họ có thể chọn trang tiếp theo hoặc nhấp vào link Xem tiếp, lúc đó ứng dụng sẽ trình bày các bản tin ở các trang tiếp theo. Tham số totalRecords cho chúng ta biết được tổng số bản tin thật sự có trong chuyên mục đó.

Lưu ý: Khi phân tích thiết kế ban đầu bạn không thể nào hình dung được hết các yêu cầu phát sinh để thiết kế trước các thao tác cần thiết. Bạn phải cập nhật bản thiết kế thường xuyên để phù hợp với yêu cầu. Bản thiết kế này vẫn còn thiếu một số chức năng cần thiết mà tôi sẽ trình bày cho các bạn trong bài viết tiếp theo, chúng ta sẽ chỉnh sửa bản thiết kế này trong quá trình phát triển ứng dụng để phù hợp với các yêu cầu phát sinh mà chúng ta chưa nhìn thấy hết khi thiết kế.
Data Access Components

Bây giờ chúng ta sẽ thiết kế các lớp dùng để truy xuất và cập nhật dữ liệu. Các hàm của các lớp DAO cũng khá đơn giản, chỉ làm nhiệm vụ cập nhật dữ liệu vào database và truy xuất dữ liệu từ database. Các bạn cũng thấy chức năng nó giống như trên lớp Business Logic, nhưng ở đây chúng ta không có bất kỳ ràng buộc logic gì, chỉ đơn giản thực hiện việc truy xuất dữ liệu mà thôi. Các business logic đã được kiểm tra trên lớp Business Logic.
Chúng ta tách biệt 2 lớp CategoryDAO (DAO – Data Access Object) và NewsDAO để dễ quản lý và thay đổi khi cần thiết. VD nếu bạn muốn thêm một thao tác truy xuất dữ liệu mới trên đối tượng News, bạn sẽ biết ngay mình phải thay đổi lớp NewsDAO. Nhưng có những thao tác bạn phải cân nhắc nên để nó lớp nào vì nó liên quan đến nhiều đối tượng, lúc đó bạn phải xét xem mục đích chính của thao tác đó là gì, thao tác trên đối tượng dữ liệu chính nào để đưa thao tác đó vào lớp phù hợp.
Thiết kế cơ sở dữ liệu

Do ứng dụng của chúng ta đơn giản nên chỉ có 2 bảng dữ liệu ánh xạ gần như 1-1 với các entities trên lớp Business Logic như sau:
Hiện thực lớp Business Logic & Data Access

Sau khi đã xong bước thiết kế, chúng ta sẽ tiến hành hiện thực 2 lớp Business và Data Access. Các bạn có thể xem source code đính kèm để biết chi tiết cách hiện thực 2 lớp này như thế nào. Lớp Presentation sẽ được thiết kế và hiện thực trong bài viết tiếp theo. Phần bên dưới tôi sẽ trình bày một số điểm chính trong cách hiện thực.
Hiện thực Data Access Components

Do ứng dụng của chúng ta đơn giản nên được giới hạn sẽ dùng với CSDL SQL Server 2000/2005 nên lớp này không được thiết kế để chạy cùng lúc với nhiều loại database khác nhau. Chúng ta sẽ dùng cái Stored Procedures để truy xuất dữ liệu an toàn và dễ thay đổi hơn, tránh bị các lỗi như SQL Injection(không thể tránh hoàn toàn nếu bạn không hiện thực đúng). Các bạn có thể xem qua một cách hiện thực một hàm cơ bản như thế nào:

public void CreateCategory(Category category)
{
using (SqlConnection connection = GetConnection())
{
SqlCommand command = new SqlCommand(“spCategoriesCreate”, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter(“@KeyName”, category.KeyName));
command.Parameters.Add(new SqlParameter(“@Name”, category.Name));
command.Parameters.Add(new SqlParameter(“@Description”, category.Description));
command.Parameters.Add(new SqlParameter(“@Picture”, category.Picture));
SqlParameter paramCategoryId = new SqlParameter(“@CategoryId”, SqlDbType.Int, 4);
paramCategoryId.Direction = ParameterDirection.Output;
command.Parameters.Add(paramCategoryId);
connection.Open();
command.ExecuteNonQuery();
if (paramCategoryId.Value != DBNull.Value)
category.CategoryId = (int)paramCategoryId.Value;
else
throw new DataAccessException(String.Format(Resources.String s.CreateEntityException, “Category”));
}
}
Stored Procedure spCategoriesCreate đơn giản được viết như sau:

CREATE PROCEDURE dbo.spCategoriesCreate
@Name nvarchar(50),
@KeyName varchar(30),
@Description ntext,
@Picture varchar(256),
@CategoryId int output
AS
INSERT INTO Categories
(
Name,
KeyName,
Description,
Picture
)
VALUES
(
@Name,
@KeyName,
@Description,
@Picture
)
SELECT @CategoryId = SCOPE_IDENTITY()

Hiện thực lớp Business Logic

Hiện thực lớp Business Logic đòi hỏi bạn phải nắm rõ các business logic của ứng dụng. Ví dụ đối với ứng dụng tin tức của chúng ta thì khi tạo một chuyên mục mới, bạn phải kiểm tra xem KeyName của chuyên mục đó đã có trong hệ thống chưa? Nếu có rồi thì phải báo lỗi, và nếu chưa có thì chúng ta kiểm tra KeyName đó có hợp lệ hay không? (Chỉ chứa kí tự alphabet, chữ số, gạch dưới và gạch ngang…).

public static void CreateCategory(Category category)
{
// Has this key name existed?
if (!CheckKey(category.KeyName))
throw new BusinessException(String.Format(Resources.Strings. KeyNameExisted, category.KeyName));
// is this key name valid?
if (!ValidateKey(category.KeyName))
throw new BusinessException(String.Format(Resources.Strings. InvalidKeyName, category.KeyName));
// ok , now save it to database
CategoryDAO categoryDAO = new CategoryDAO();
categoryDAO.CreateCategory(category);
}

Binding data vào treeview trong C#

Đầu tiên bạn cần tạo dataset như hình

Sau đó thêm một classs ở đây tui đặt tên là clsTreeview.cs
pase code này vào treeview

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsFormsApplication1
{
    class clsTreeview
    {
        public class BangKhoa_lop
        {
            public const string Khoa = "Khoa";
            public const string Lop = "Lop";
        }
        public class KhoaField
        {
            public const string MaKhoa = "MaKhoa";
            public const string TenKhoa = "TenKhoa";
        }
        public class LopField
        {
            public const string MaLop = "MaLop";
            public const string TenLop = "TenLop";
        }
        DataRelation relLop_Khoa;
        DHTayNguyenDataSet ds =new DHTayNguyenDataSet();

        public clsTreeview()
        {
            DHTayNguyenDataSetTableAdapters.LopTableAdapter atp = new WindowsFormsApplication1.DHTayNguyenDataSetTableAdapters.LopTableAdapter();
            atp.Fill(ds.Lop);
            DHTayNguyenDataSetTableAdapters.KhoaTableAdapter KhoaAdapter = new WindowsFormsApplication1.DHTayNguyenDataSetTableAdapters.KhoaTableAdapter();
            KhoaAdapter.Fill(ds.Khoa);
             relLop_Khoa = new DataRelation("QHLop_Khoa",
                ds.Tables["Khoa"].Columns["MaKhoa"],
                ds.Tables["Lop"].Columns["MaKhoa"]);
                ds.Relations.Add(relLop_Khoa);
        }
        public DataTable GetKhoa()
        {
           return ds.Tables["Khoa"];

        }
        public DataRow[] GetLopTrongKhoa(DataRow rowParent)
        {
            return rowParent.GetChildRows(relLop_Khoa);
        }
        public string GetDisplayText(DataRow row)
        {
            string text = "";

            switch (row.Table.TableName)
            {
                case BangKhoa_lop.Lop:
                    text = "ID: " + row[0] + "\n";
                    text += "MaLop: " + row[LopField.MaLop] + "\n";
                    text += "Tên Lớp: "+row[LopField.TenLop];
                    break;
            }
            return text;
        }
    }
}

Chú ý khai báo các biến toàn cục

private clsTreeview dd = new clsTreeview();

Tiếp theo trong formload thêm cái này vào

private void Form1_Load(object sender, EventArgs e)
        {
            TreeNode Node;
            foreach (DataRow dr in dd.GetKhoa().Rows)
            {
                Node = treeView1.Nodes.Add(dr[clsTreeview.KhoaField.TenKhoa].ToString());
                Node.ImageIndex = 0;
                Node.Tag = dr;
                Node.Nodes.Add("*");
            }

        }

Event BeforeExpand của treeview như sau
Mục đích chỉ load phần nào cần, chưa cần thì chưa load

private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            TreeNode NodeSelected, nodeChild;
            NodeSelected = e.Node;

            if (NodeSelected.Nodes[0].Text == "*")
            {
                NodeSelected.Nodes.Clear();

                foreach (DataRow row in
                    dd.GetLopTrongKhoa((DataRow)NodeSelected.Tag))
                {
                    nodeChild = NodeSelected.Nodes.Add(row[clsTreeview.LopField.TenLop].ToString());
                    nodeChild.Tag = row;
                    nodeChild.ImageIndex = 1;
                    nodeChild.SelectedImageIndex = 1;
                }
            }

        }

Để hiển thị dữ liệu ta cần event AfterSelect của treeview

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            richTextBox1.Text = dd.GetDisplayText((DataRow)e.Node.Tag);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("ddddddd");
            foreach (TreeNode node in treeView1.Nodes)
            {
               if(node.Nodes == null)
                {
                    MessageBox.Show(node.Text.ToString());
                }
            }
        }

Chú ý là trên form có 2 đối tượng là treewview và richtextbox
Chạy chương trình ta có kết quả
Ảnh
từ đây bạn có thể phát triển các class này lên để phù hợp với mục đích sử dụng
Chúc thành công

Kéo thả trong lưới delphi -Drag and drop operations with Delphi’s DBGrid

Dragging and dropping is a convenient way for users to manipulate data. You can let users drag an entire control, or let them drag items from one control to another, or drag and drop nodes of a tree view (for example).
Each Delphi control exposes several events (OnDragOver, OnDragDrop) and properties (DragMode) you use to program drag and drop operations in your applications.
In order to start a drag operation for a control, you either have to set the DragMode property to dmAutomatic, or leave it to dmManual (default) and manually call the BeginDrag method. BeginDrag starts the dragging of a control. When we have started the drag operation we need to have a component that will act as a drop target.
To enable a control to accept an object being draged you have to code two events: OnDragOver (to signal that the control can accept a dragged object) and OnDragDrop (to specify what happens when the user drops an object).

In Delphi database applications, where TDBGrid is used to enable a user to view and edit data in a tabular grid, dragging and dropping can come quite handy. Let’s see how to add drag and drop capabilities to DBGrid.
Dragging FROM a DBGrid

Let’s say you have a DBGrid attached to some Dataset object displaying some data from a database. Here’s what needs to be coded if you want to enable a user to drag the selected record to a TMemo control, for example. 1. Handle the OnCellClick event of a DBGrid (Name := ‘DBGrid1′) to start the drag operation:

procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
DBGrid1.BeginDrag(true);
end;

2. Specify that a Memo control (Name := ‘Memo1′) can accept data from a DBGrid, using the OnDragDrop event of a Memo:

procedure TForm1.Memo1DragOver(
Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := Source IS TDBGrid;
end; 

3. Finally, handle the OnDragDrop of a Memo control to process data being dropped. We’ll add the code to add the values of all the fields of the current record to a Memo control:

procedure TForm1.Memo1DragDrop(
Sender, Source: TObject;
X, Y: Integer);
var i : integer;
begin
Memo1.Clear;

for i := 0 to -1 + DBGrid1.FieldCount do
begin
Memo1.Lines.Add(DBGrid1.Fields[i].AsString);
end;
end;


Once you have a running application, click on a row in a DBGrid (to make the row/record active) then click inside the Memo control: Memo gets filled with the values of the fields from the selected (dragged record).
Dragging TO a DBGrid

While dragging FROM a DBGrid turns to be easy to program, dragging TO a DBGrid is quite a tricky task. Suppose you have a ListBox filled with items, and want to enable a user to drag an item to a particular cell (e.g. to edit one particular field) of a DBGrid – to change the value of a specific field. How do you determine the exact row and the exact cell of a DBGrid where the user has finished the drag operation?

As discussed in the “accessing protected members of a component” article, many Delphi components have useful properties and methods that are marked invisible (“protected”) to a Delphi developer.
When a user finishes the drag operation and drops a value over a cell in a DBGrid, we have to set the active record, place the underlying dataset into edit mode, and assign a value to a particular field.

Here’s the code needed to handle dragging to a DBGrid:
1. Since we are dropping items from a ListBox control, by handling the OnDragOver of a DBGrid we specify that only items from a ListBox are acceptable to be dropped on a DBGrid:

 procedure TForm1.DBGrid1DragOver(
Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := Source IS TListBox;
end;

2. The tricky part goes in the OnDragDrop event handler for DBGrid:

</div>
<div>procedure TForm1.DBGrid1DragDrop(
Sender, Source: TObject; X, Y: Integer);
var
gc : TGridCoord;
s : string;
begin
gc := THackDBGrid(DBGrid1).MouseCoord(X,Y);
if (gc.X > 0) AND (gc.Y > 0) then
begin
if ListBox1.ItemIndex = -1 then Exit;
s := ListBox1.Items[ListBox1.ItemIndex];</div>
<div>

with THackDBGrid(DBGrid1) do
begin
DataSource.DataSet.MoveBy (gc.Y - Row);
DataSource.DataSet.Edit;
Columns.Items[-1 + gc.X].Field.AsString := s;
end;
end;
end; 


Note: We first use the protected hack to get our hands on the protected MouseCoord method to access the row and column of a DBGrid. This technique is explained in the Selecting and highlighting a row in a DBGrid – “OnMouseOverRow” article. If the target is not the first row (where column titles are by default) and not the first column (where row indicator is by default) we set the current row using the MoveBy method and the Row property. Next, dataset is put into edit mode. Finally, the value of the target field is assigned using the selected item from the ListBox.
That’s it. If you are looking for more DBGrid related article, check the “TDBGrid to the MAX” collection. More drag and drop ideas can be found here: dragging and dropping with Delphi.
Nguồn: http://delphi.about.com/library/weekly/aa042605a.htm

Kéo thả giữa 2 lưới trên form Vb.Net

Kéo 2 lưới ra form rồi chọn thuộc tính Allowdrop=true sau đó chạy thử

Public Class frmDataGrid
    ' Some Properties that I have set for the Grid
    ' SelectionMode = FullRowSelect [For both the Grids]
    ' AllowDrop = True [For Grid DataGridView2]
    '
    '
    Dim DT1 As DataTable
    Dim DT2 As DataTable

    Private Sub frmDataGrid_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        FillDataInGrids()
    End Sub

    Private Sub FillDataInGrids()
        DT1 = New DataTable
        DT2 = New DataTable

        'The First Table has four columns
        DT1.Columns.Add("Name", Type.GetType("System.String"))
        DT1.Columns.Add("Designation", Type.GetType("System.String"))
        DT1.Columns.Add("Department", Type.GetType("System.String"))
        DT1.Columns.Add("Salary", Type.GetType("System.String"))

        'Second has only two
        DT2.Columns.Add("Name", Type.GetType("System.String"))
        DT2.Columns.Add("Designation", Type.GetType("System.String"))

        'Now Add some Rows in the first DataTable
        Dim Dr As DataRow

        Dr = DT1.NewRow
        Dr("Name") = "Tom"
        Dr("Designation") = "Developer"
        Dr("Department") = "Engg"
        Dr("Salary") = "1000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Jerry"
        Dr("Designation") = "Developer"
        Dr("Department") = "Engg"
        Dr("Salary") = "1000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Micky"
        Dr("Designation") = "Analyst"
        Dr("Department") = "Engg"
        Dr("Salary") = "2000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Mini"
        Dr("Designation") = "Analyst"
        Dr("Department") = "Engg"
        Dr("Salary") = "2000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Donald"
        Dr("Designation") = "Manager"
        Dr("Department") = "Engg"
        Dr("Salary") = "3000"
        DT1.Rows.Add(Dr)

        'Now Bind the DataGrids to these table
        DGV1.DataSource = DT1
        DGV2.DataSource = DT2

    End Sub

    Private Sub DataGridView1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseDown
        'Get the Index of Row which is being Dragged
        'We would use this Index on Drop to identify which Row was dragged and get the values from that row
        Dim Index As Integer
        Index = DataGridView1.HitTest(e.X, e.Y).RowIndex
        If Index > -1 Then
            'Pass the Index as "Data" argument of the DoDragDrop Function
            DataGridView1.DoDragDrop(Index, DragDropEffects.Move)
        End If
      End Sub

    Private Sub DataGridView2_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView2.DragOver
        'Just to Show a mouse icon to denote drop is allowed here
        e.Effect = DragDropEffects.Move
    End Sub

    Private Sub DataGridView2_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView2.DragDrop
        Try
            'Get the Index value that we stored in the Data in the MouseDown event
            'In case we stored a PrimaryKey value here in place of Index, we would get that by Type casting it to its type
            Dim index As Integer = Convert.ToInt32(e.Data.GetData(Type.GetType("System.Int32")))

            'Now based on the Index get the data in the Cells
            'Again if we had Primary Key value here we would have used the underlying DataTable DT1 to get the data for that key
            Dim Name As String
            Dim Desig As String
            Name = DataGridView1.Rows(index).Cells("Name").Value.ToString
            Desig = DataGridView1.Rows(index).Cells("Designation").Value.ToString
            Dim Dr As DataRow
            Dr = DT2.NewRow
            Dr("Name") = Name
            Dr("Designation") = Desig
            DT2.Rows.Add(Dr)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

    End Sub

End Class

Nguồn

http://www.dotnetspider.com/resources/2698-Drag-drop-DataGrid-VB-NET–windows-application.aspx

Conversion Operators in to LINQ

1. ToSequence
The ToSequence operator returns its argument typed as IEnumerable.

public static IEnumerable</t><t> ToSequence</t><t>(
this IEnumerable</t><t> source);

The ToSequence operator simply returns the source argument. The operator has no effect other than to change the compile-time type of the source argument to IEnumerable.
The ToSequence operator can be used to choose between query operator implementations in cases where a collection implements IEnumerable
but also has a different set of public query operators. For example, given a class Table that implements IEnumerable as well as its own Where, Select, SelectMany, and so on, the query

Table<customer> custTable = GetCustomersTable();
var query = custTable.Where(c => IsGoodCustomer(c));

will invoke the public Where operator of Table. A Table type that represents a database table would likely have a Where operator that takes the predicate argument as an expression tree and converts the tree into SQL for remote execution. If remote execution is not desired, for example because the predicate invokes a local method, the ToSequence operator can be used to hide Table’s operators and instead make the Standard Query Operators available:

Table<customer> custTable = GetCustomersTable();
var query = custTable.ToSequence().Where(c => IsGoodCustomer(c));

This would now cause the query to execute locally.

2. ToArray

The ToArray operator creates an array from a sequence.

public static T[] ToArray<t>(
this IEnumerable</t><t> source);

The ToArray operator enumerates the source sequence and returns an array containing the elements of the sequence. An ArgumentNullException is thrown if the source argument is null.
The following example produces an array of the names of all countries in which there are customers:

string[] customerCountries =
customers.Select(c => c.Country).Distinct().ToArray();

3. ToList
The ToList operator creates a List from a sequence.

public static List</t><t> ToList</t><t>(
this IEnumerable</t><t> source);

The ToList operator enumerates the source sequence and returns a List containing the elements of the sequence. An ArgumentNullException is thrown if the source argument is null.
The following example produces a List containing those customers that placed orders in 2005:

List</customer><customer> customersWithOrdersIn2005 =
customers.
Where(c => c.Orders.Any(o => o.OrderDate.Year == 2005)).
ToList();

4. ToDictionary
The ToDictionary operator creates a Dictionary from a sequence.

public static Dictionary</k><k , T> ToDictionary<t , K>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector);
public static Dictionary<k , T> ToDictionary<t , K>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector,
IEqualityComparer<k> comparer);
public static Dictionary</k><k , E> ToDictionary<t , K, E>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector,
Func</t><t , E> elementSelector);
public static Dictionary<k , E> ToDictionary<t , K, E>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector,
Func</t><t , E> elementSelector,
IEqualityComparer<k> comparer);

The ToDictionary operator enumerates the source sequence and evaluates the keySelector and elementSelector functions for each element to produce that element’s key and value. The resulting key and value pairs are returned in a Dictionary. If no elementSelector was specified, the value for each element is simply the element itself. An ArgumentNullException is thrown if the source, keySelector, or elementSelector argument is null or if a key value produced by keySelector is null. An ArgumentException is thrown if keySelector produces a duplicate key value for two elements. In the resulting dictionary, key values are compared using the given comparer, or, if a null comparer was specified, using the default equality comparer, EqualityComparer.Default.
The following example creates a Dictionary that maps from order ID to order for all orders in 2005:

Dictionary</int><int ,Order> orders =
customers.
SelectMany(c => c.Orders).
Where(o => o.OrderDate.Year == 2005).
ToDictionary(o => o.OrderID);

The following example creates a Dictionary that maps from category name to the maximum product price in that category:

Dictionary</string><string ,decimal> categoryMaxPrice =
products.
GroupBy(p => p.Category).
ToDictionary(g => g.Key, g => g.Group.Max(p => p.UnitPrice));


5. ToLookup

The ToLookup operator creates a Lookup from a sequence.

public static Lookup</k><k , T> ToLookup<t , K>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector);
public static Lookup<k , T> ToLookup<t , K>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector,
IEqualityComparer<k> comparer);
public static Lookup</k><k , E> ToLookup<t , K, E>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector,
Func</t><t , E> elementSelector);
public static Lookup<k , E> ToLookup<t , K, E>(
this IEnumerable</t><t> source,
Func</t><t , K> keySelector,
Func</t><t , E> elementSelector,
IEqualityComparer<k> comparer);
public class Lookup</k><k , T> : IEnumerable<igrouping <K, T>>
{
public int Count { get; }
public IEnumerable<t> this[K key] { get; }
public bool Contains(K key);
public IEnumerator<igrouping <K, T>> GetEnumerator();
}

Lookup implements a one-to-many dictionary that maps keys to sequences of values. This contrasts with Dictionary which implements a one-to-one dictionary that maps keys to single values. The functionality provided by Lookup is used in the implementations of the Join, GroupJoin, and GroupBy operators.
The ToLookup operator enumerates the source sequence and evaluates the keySelector and elementSelector functions for each element to produce that element’s key and value. The resulting key and value pairs are returned in a Lookup
. If no elementSelector was specified, the value for each element is simply the element itself. An ArgumentNullException is thrown if the source, keySelector, or elementSelector argument is null. When creating the Lookup, key values are compared using the given comparer, or, if a null comparer was specified, using the default equality comparer, EqualityComparer.Default.
The following example creates a Lookup that maps from category name to the sequence of products in that category:

Lookup</string><string ,Product> productsByCategory =
products.ToLookup(p => p.Category);
IEnumerable<product> beverages = productsByCategory["Beverage"];

6. OfType
The OfType operator filters the elements of a sequence based on a type.

public static IEnumerable<t> OfType</t><t>(
this IEnumerable source);

The OfType operator allocates and returns an enumerable object that captures the source argument. An ArgumentNullException is thrown if the source argument is null.
When the object returned by OfType is enumerated, it enumerates the source sequence and yields those elements that are of type T. Specifically, each element e for which e is T evaluates to true is yielded by evaluating (T)e.
Given a class Employee that inherits from a class Person, the following example returns all employees from a list of persons:

List<person> persons = GetListOfPersons();
IEnumerable<employee> employees = persons.OfType</employee><employee>();

7. Cast
The Cast operator casts the elements of a sequence to a given type.

public static IEnumerable<t> Cast</t><t>(
this IEnumerable source);

The Cast operator allocates and returns an enumerable object that captures the source argument. An ArgumentNullException is thrown if the source argument is null.
When the object returned by Cast is enumerated, it enumerates the source sequence and yields each element cast to type T. An InvalidCastException is thrown if an element in the sequence cannot be cast to type T.
The Cast operator can be used to bridge between non-generic collections and the Standard Query Operators. For example, the non-generic ArrayList doesn’t implement IEnumerable, but the Cast operator can be used to supply the missing type information:

ArrayList objects = GetOrders();
IEnumerable<order> ordersIn2005 =
objects.
Cast</order><order>().
Where(o => o.OrderDate.Year == 2005);

In a C# 3.0 query expression, an explicitly typed iteration variable translates to an invocation of Cast. The example above is equivalent to the translation of

ArrayList objects = GetOrders();
IEnumerable</order><order> ordersIn2005 =
from Order o in objects
where o.OrderDate.Year == 2005
select o;

How to Script User and Role Object Permissions in SQL Server

From time to time, I need the ability to “reverse engineer” SQL Server object permissions, for either users or roles, from one database, and then “move” them to another version of the database on another server. For example, I have a development database which developers use to experiment with various Visual Basic applications they write. As they write these apps, I go in and manually set the necessary permissions for these apps to work. Sometimes, this is a trial and error approach, and the permissions evolve over the design and testing of the application. At some point, the developer is ready to role out the app to production, and now I need to “move” the necessary object permissions from the development database to the production database.

While there are third party tools to do this, I didn’t have any handy, so I came up with the following two scripts to do this work for me. The first script is used to reverse engineer object permissions (based on a specific user), and the results of this script are used to recreate the same permissions in a different database. The second script is used to reverse engineer permissions (based on SQL Server database roles), and the results of this script are used to recreate the same permissions on a different database.
Script to Reverse Engineer SQL Server Object User Permissions

--Written By Bradley Morris
--In Query Analyzer be sure to go to
--Query -> Current Connection Options -> Advanced (Tab)
--and set Maximum characters per column
--to a high number, such as 10000, so
--that all the code will be displayed.

DECLARE @DatabaseUserName [sysname]
SET @DatabaseUserName = 'user_name_goes_here'

SET NOCOUNT ON
DECLARE
@errStatement [varchar](8000),
@msgStatement [varchar](8000),
@DatabaseUserID [smallint],
@ServerUserName [sysname],
@RoleName [varchar](8000),
@ObjectID [int],
@ObjectName [varchar](261)

SELECT
@DatabaseUserID = [sysusers].[uid],
@ServerUserName = [master].[dbo].[syslogins].[loginname]
FROM [dbo].[sysusers]
INNER JOIN [master].[dbo].[syslogins]
ON [sysusers].[sid] = [master].[dbo].[syslogins].[sid]
WHERE [sysusers].[name] = @DatabaseUserName
IF @DatabaseUserID IS NULL
BEGIN
SET @errStatement = 'User ' + @DatabaseUserName + ' does not exist in ' + DB_NAME() + CHAR(13) +
'Please provide the name of a current user in ' + DB_NAME() + ' you wish to script.'
RAISERROR(@errStatement, 16, 1)
END
ELSE
BEGIN
SET @msgStatement = '--Security creation script for user ' + @ServerUserName + CHAR(13) +
'--Created At: ' + CONVERT(varchar, GETDATE(), 112) + REPLACE(CONVERT(varchar, GETDATE(), 108), ':', '') + CHAR(13) +
'--Created By: ' + SUSER_NAME() + CHAR(13) +
'--Add User To Database' + CHAR(13) +
'USE [' + DB_NAME() + ']' + CHAR(13) +
'EXEC [sp_grantdbaccess]' + CHAR(13) +
CHAR(9) + '@loginame = ''' + @ServerUserName + ''',' + CHAR(13) +
CHAR(9) + '@name_in_db = ''' + @DatabaseUserName + '''' + CHAR(13) +
'GO' + CHAR(13) +
'--Add User To Roles'
PRINT @msgStatement
DECLARE _sysusers
CURSOR
LOCAL
FORWARD_ONLY
READ_ONLY
FOR
SELECT
[name]
FROM [dbo].[sysusers]
WHERE
[uid] IN
(
SELECT
[groupuid]
FROM [dbo].[sysmembers]
WHERE [memberuid] = @DatabaseUserID
)
OPEN _sysusers
FETCH
NEXT
FROM _sysusers
INTO @RoleName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @msgStatement = 'EXEC [sp_addrolemember]' + CHAR(13) +
CHAR(9) + '@rolename = ''' + @RoleName + ''',' + CHAR(13) +
CHAR(9) + '@membername = ''' + @DatabaseUserName + ''''
PRINT @msgStatement
FETCH
NEXT
FROM _sysusers
INTO @RoleName
END
SET @msgStatement = 'GO' + CHAR(13) +
'--Set Object Specific Permissions'
PRINT @msgStatement
DECLARE _sysobjects
CURSOR
LOCAL
FORWARD_ONLY
READ_ONLY
FOR
SELECT
DISTINCT([sysobjects].[id]),
'[' + USER_NAME([sysobjects].[uid]) + '].[' + [sysobjects].[name] + ']'
FROM [dbo].[sysprotects]
INNER JOIN [dbo].[sysobjects]
ON [sysprotects].[id] = [sysobjects].[id]
WHERE [sysprotects].[uid] = @DatabaseUserID
OPEN _sysobjects
FETCH
NEXT
FROM _sysobjects
INTO
@ObjectID,
@ObjectName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @msgStatement = ''
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 193 AND [protecttype] = 205)
SET @msgStatement = @msgStatement + 'SELECT,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 195 AND [protecttype] = 205)
SET @msgStatement = @msgStatement + 'INSERT,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 197 AND [protecttype] = 205)
SET @msgStatement = @msgStatement + 'UPDATE,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 196 AND [protecttype] = 205)
SET @msgStatement = @msgStatement + 'DELETE,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 224 AND [protecttype] = 205)
SET @msgStatement = @msgStatement + 'EXECUTE,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 26 AND [protecttype] = 205)
SET @msgStatement = @msgStatement + 'REFERENCES,'
IF LEN(@msgStatement) > 0
BEGIN
IF RIGHT(@msgStatement, 1) = ','
SET @msgStatement = LEFT(@msgStatement, LEN(@msgStatement) - 1)
SET @msgStatement = 'GRANT' + CHAR(13) +
CHAR(9) + @msgStatement + CHAR(13) +
CHAR(9) + 'ON ' + @ObjectName + CHAR(13) +
CHAR(9) + 'TO ' + @DatabaseUserName
PRINT @msgStatement
END
SET @msgStatement = ''
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 193 AND [protecttype] = 206)
SET @msgStatement = @msgStatement + 'SELECT,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 195 AND [protecttype] = 206)
SET @msgStatement = @msgStatement + 'INSERT,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 197 AND [protecttype] = 206)
SET @msgStatement = @msgStatement + 'UPDATE,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 196 AND [protecttype] = 206)
SET @msgStatement = @msgStatement + 'DELETE,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 224 AND [protecttype] = 206)
SET @msgStatement = @msgStatement + 'EXECUTE,'
IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 26 AND [protecttype] = 206)
SET @msgStatement = @msgStatement + 'REFERENCES,'
IF LEN(@msgStatement) > 0
BEGIN
IF RIGHT(@msgStatement, 1) = ','
SET @msgStatement = LEFT(@msgStatement, LEN(@msgStatement) - 1)
SET @msgStatement = 'DENY' + CHAR(13) +
CHAR(9) + @msgStatement + CHAR(13) +
CHAR(9) + 'ON ' + @ObjectName + CHAR(13) +
CHAR(9) + 'TO ' + @DatabaseUserName
PRINT @msgStatement
END
FETCH
NEXT
FROM _sysobjects
INTO
@ObjectID,
@ObjectName
END
CLOSE _sysobjects
DEALLOCATE _sysobjects
PRINT 'GO'
END

http://www.sql-server-performance.com/articles/dba/object_permission_scripts_p1.aspx

SQL Script lấy toàn bộ các roles và user có quyền truy cập vào database

SQL Script to return user accounts and the roles they are assigned to…

This script will return a list of all logins that are in use on the current database and also the creation date and modified date of the user. Also the roles that they are assigned to are also returned.

This can be useful to companies who must audit their SQL server databases for SOX compliance.

-- Process
--     Create Temp Table for Users
--    Create Temp Table for Roles
--    Populate Users
--    Populate Roles
--    Iterate though each user and update their roles into a single column
--    Return the users and their roles
Create Table #Temp_Users
(
    Name             varchar(128),
    CreateDate        datetime,
    LastModifiedDate    datetime,
    LoginType        varchar(50),
    Roles            varchar(1024)
)

Create Table #Temp_Roles
(
    Name             varchar(128),
    Role            varchar(128)
)

insert into #Temp_Users
select Name, [Create Date] = CreateDate, [Last Modified Date] = UpdateDate,
    LoginType = case
        when IsNTName = 1 then 'Windows Account'
        when IsNTGroup = 1 then 'Windows Group'
        when isSqlUser = 1 then 'SQL Server User'
        when isAliased =1 then 'Aliased'
        when isSQLRole = 1 then 'SQL Role'
        when isAppRole = 1 then 'Application Role'
        else 'Unknown'
        end,
    Roles = ''
from sysusers
where SID is not null
order by Name

insert into #Temp_Roles
select MemberName = u.name, DbRole = g.name
            from sysusers u, sysusers g, sysmembers m
            where   g.uid = m.groupuid
                and g.issqlrole = 1
                and u.uid = m.memberuid
            order by 1, 2

Declare @Name    varchar(128)
Declare @Roles    varchar(1024)
Declare @Role    varchar(128)

DECLARE UserCursor CURSOR for
SELECT name from #Temp_Users
OPEN UserCursor
FETCH NEXT FROM UserCursor into @Name
WHILE @@FETCH_STATUS = 0
BEGIN
    set @Roles = ''
    print @Name
    DECLARE RoleCursor CURSOR for
    SELECT Role from #Temp_Roles where Name = @Name

    OPEN RoleCursor
    FETCH NEXT FROM RoleCursor into @Role
    WHILE @@FETCH_STATUS = 0
    BEGIN
        if (@Roles > '')
            set @Roles = @Roles + ', '+@Role
        else
            set @Roles = @Role
        FETCH NEXT FROM RoleCursor into @Role
    end
    Close RoleCursor
    DEALLOCATE RoleCursor
    Update #Temp_Users set Roles = @Roles where Name = @Name
       FETCH NEXT FROM UserCursor into @Name
END
CLOSE UserCursor
DEALLOCATE UserCursor

select * from #Temp_Users

drop table #Temp_Users
drop table #Temp_Roles

http://blog.crowe.co.nz/archive/2006/02/18/558.aspx

CopyURLToFile – Download a file from the Internet via FTP or HTTP

Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Const INTERNET_FLAG_EXISTING_CONNECT = &amp;H20000000

Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
    (ByVal lpszAgent As String, ByVal dwAccessType As Long, _
    ByVal lpszProxyName As String, ByVal lpszProxyBypass As String, _
    ByVal dwFlags As Long) As Long
Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias _
    "InternetOpenUrlA" (ByVal hInternetSession As Long, ByVal lpszUrl As String, _
    ByVal lpszHeaders As String, ByVal dwHeadersLength As Long, _
    ByVal dwFlags As Long, ByVal dwContext As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As _
    Long) As Integer
Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As _
    Long, ByVal lpBuffer As String, ByVal dwNumberOfBytesToRead As Long, _
    lNumberOfBytesRead As Long) As Integer

' Download a file from Internet and save it to a local file
'
' it works with HTTP and FTP, but you must explicitly include
' the protocol name in the URL, as in
'    CopyURLToFile "http://www.vb2themax.com/default.asp", "C:\vb2themax.htm"

Sub CopyURLToFile(ByVal URL As String, ByVal FileName As String)
    Dim hInternetSession As Long
    Dim hUrl As Long
    Dim FileNum As Integer
    Dim ok As Boolean
    Dim NumberOfBytesRead As Long
    Dim Buffer As String
    Dim fileIsOpen As Boolean

    On Error GoTo ErrorHandler

    ' check obvious syntax errors
    If Len(URL) = 0 Or Len(FileName) = 0 Then Err.Raise 5

    ' open an Internet session, and retrieve its handle
    hInternetSession = InternetOpen(App.EXEName, INTERNET_OPEN_TYPE_PRECONFIG, _
        vbNullString, vbNullString, 0)
    If hInternetSession = 0 Then Err.Raise vbObjectError + 1000, , _
        "An error occurred calling InternetOpen function"

    ' open the file and retrieve its handle
    hUrl = InternetOpenUrl(hInternetSession, URL, vbNullString, 0, _
        INTERNET_FLAG_EXISTING_CONNECT, 0)
    If hUrl = 0 Then Err.Raise vbObjectError + 1000, , _
        "An error occurred calling InternetOpenUrl function"

    ' ensure that there is no local file
    On Error Resume Next
    Kill FileName

    On Error GoTo ErrorHandler

    ' open the local file
    FileNum = FreeFile
    Open FileName For Binary As FileNum
    fileIsOpen = True

    ' prepare the receiving buffer
    Buffer = Space(4096)

    Do
        ' read a chunk of the file - returns True if no error
        ok = InternetReadFile(hUrl, Buffer, Len(Buffer), NumberOfBytesRead)

        ' exit if error or no more data
        If NumberOfBytesRead = 0 Or Not ok Then Exit Do

        ' save the data to the local file
        Put #FileNum, , Left$(Buffer, NumberOfBytesRead)
    Loop

    ' flow into the error handler

ErrorHandler:
    ' close the local file, if necessary
    If fileIsOpen Then Close #FileNum
    ' close internet handles, if necessary
    If hUrl Then InternetCloseHandle hUrl
    If hInternetSession Then InternetCloseHandle hInternetSession

    ' report the error to the client, if there is one
    If Err Then Err.Raise Err.Number, , Err.Description
End Sub

http://www.devx.com/vb2themax/Tip/19203