Đào Hải Nam

Sử dụng LINQ to SQL (LINQ to SQL phần 1)

Posted in Không phân loại, Microsoft .NET by namdh on 08/10/2008

Đây là bài viết đầu tiên trong loạt bài có chủ đề “LINQ to SQL”, các bài này sẽ cho bạn một cái nhìn khái quát, giúp bạn làm quen với LINQ, một trong những công nghệ mới có trong .NET 3.5.

Loạt bài này được dựa trên loạt Tutorial của ScottGu (http://weblogs.asp.net/scottgu).

LINQ to SQL là gì?

LINQ to SQL là một phiên bản hiện thực hóa của O/RM (object relational mapping) có bên trong .NET Framework bản “Orcas” (nay là .NET 3.5), nó cho phép bạn mô hình hóa một cơ sở dữ liệu dùng các lớp .NET. Sau đó bạn có thể truy vấn cơ sở dữ liệu (CSDL) dùng LINQ, cũng như cập nhật/thêm/xóa dữ liệu từ đó.

LINQ to SQL hỗ trợ đầy đủ transaction, view và các stored procedure (SP). Nó cũng cung cấp một cách dễ dàng để thêm khả năng kiểm tra tính hợp lệ của dữ liệu và các quy tắc vào trong mô hình dữ liệu của bạn.

Mô hình hóa CSDL dùng LINQ to SQL:

Visual Studio “Orcas” đã tích hợp thêm một trình thiết kế LINQ to SQL như một công cụ dễ dàng cho việc mô hình hóa một cách trực quan các CSDL dùng LINQ to SQL.  Bài viết sau sẽ đi sâu hơn vào cách dùng trình thiết kế này (bạn cũng có thể xem đoạn video này để xem cách tôi tạo một mô hình LINQ to SQL).

Bằng cách dùng trình thiết kế LINQ to SQL, tôi có thể dễ dàng tạo một mô hình cho CSDL mẫu “Northwind” giống như dưới đây:

Mô hình LINQ to SQL ở trên định nghĩa bốn lớp thực thể: Product, Category, Order và OrderDetail. Các thuộc tính của mỗi lớp ánh xạ vào các cột của bảng tương ứng trong CSDL. Mỗi instance của một lớp biểu diễn một dòng trong bảng dữ liệu.

Các mũi tên giữa bốn lớp thực thể trên biểu diễn quan hệ giữa các thực thể khác nhau, chúng được tạo ra dựa trên các mối quan hệ primary-key/foreign-key trong CSDL. Hướng của mũi tên chỉ ra mối quan hệ là một – một hay một – nhiều. Các thuộc tính tương ứng sẽ được thêm vào các lớp thực thể trong các trường hợp này. Lấy ví dụ, lớp Category ở trên có một mối quan hệ một nhiều với lớp Product, điều này có nghĩa nó sẽ có một thuộc tính “Categories” là một tập hợp các đối tượng Product trong Category này. Lớp Product cũng sẽ có một thuộc tính “Category” chỉ đến đối tượng ”Category” chứa Product này bên trong.

Bảng các phương thức bên tay phải  bên trong trình thiết kế LINQ to SQL ở trên chứa một danh sách các SP để tương tác với mô hình dữ liệu của chúng ta. Trong ví dụ trên tôi đã thêm một thủ tục có tên “GetProductsByCategory”. Nó nhận vào một categoryID và trả về một chuỗi các Product. Chúng ta sẽ xem bằng cách nào có thể gọi được thủ tục này trong một đoạn code bên dưới.

Tìm hiểu lớp DataContext

Khi bạn bấm nút “Save” bên trong màn hình thiết kế LINQ to SQL, Visual Studio sẽ lưu các lớp .NET biểu diễn các thực thể và quan  hệ bên trong CSDL mà chúng ta vừa mô hình hóa. Cứ mỗi một file LINQ to SQL chúng ta thêm vào solution, một lớp DataContext sẽ được tạo ra, nó sẽ được dùng khi cần truy vấn hay cập nhật lại các thay đổi. Lớp DataContext được tạo sẽ có các thuộc tính để biểu diễn mối bảng được mô hình hóa từ CSDL, cũng như các phương thức cho mỗi SP mà chúng ta đã thêm vào.

Lấy ví dụ, dưới đây là lớp NorthwindDataContext được sinh ra dựa trên mô hình chúng ta tạo ra ở trên:

Các ví dụ LINQ to SQL

Một khi đã mô hình hóa CSDL dùng trình thiết kế LINQ to SQL, chúng ta có thể dễ dàng viết các đoạn lệnh để làm việc với nó. Dưới đây là một vài ví dụ về các thao tác chung khi xử lý dữ liệu:

1) Lấy các Product từ CSDL

Đoạn lệnh dưới đây dùng cú pháp LINQ để lấy về một tập IEnumerable các đối tượng Product. Các sản phẩm được lấy ra phải thuộc phân loại “Beverages”:

C#:

VB:

2) Cập nhật một sản phẩm trong CSDL

Đoạn lệnh dưới đây cho thấy cách lấy một sản phẩm, cập nhật lại giá tiền và lưu lại CSDL.

C#:

VB:

3) Chèn thêm một phân loại mới và hai sản phẩm vào CSDL

Đoạn mã dưới đây biểu diễn cách tạo một phân loại mới, và tạo hai sản phẩm mới và đưa chúng vào trong phân loại đã tạo. Cả ba sau đó sẽ được đưa vào cơ sở dữ liệu.

Chú ý rằng tôi không cần phải tự quản lý các mối quan hệ primary key/foreign key, thay vào đó, tôi chỉ đơn giản thêm các đối tượng Product vào tập hợp Products của đối tượng category, và rồi thêm đối tượng category vào tập hợp Categories của DataContext, LINQ to SQL sẽ biết cách thiết lập các giá trị primary key/foreign key một cách thích hợp.

(Add đã được thay đổi bằng InsertOnSubmit trong phiên bản hiện tại)

C#

VB:

4) Xóa các sản phẩm

Đoạn mã sau sẽ biểu diễn cách xóa tất cả các sản phẩm Toy khỏi CSDL:

(RemoveAll đã được thay đổi bằng DeleteAllOnSubmit trong phiên bản hiện tại)

C#:

VB:

5) Gọi một thủ tục

Đoạn mã dưới đây biểu diễn cách lấy các thực thể Product mà không dùng cú pháp của LINQ, mà gọi đến thủ tục “GetProductsByCategory” chúng ta đã thêm vào trước đây. Nhớ rằng một khi đã lấy về kết quả, tôi có thể cập nhật/xóa và sau đó gọi db.SubmitChanges() để cập nhật các thay đổi trở lại CSDL.

C#:

VB:

6) Lấy các sản phẩm và phân trang

Đoạn mã dưới đây biểu diễn cách phân trang trên server như một phần của câu truy vấn LINQ. Bằng cách dùng các toán tử Skip() và Take(), chúng ta sẽ chỉ trả về 10 dòng từ CSDL – bắt đầu từ dòng 200.

C#:

VB:

Tổng kết

LINQ to SQL cung cấp một cách hay, rõ ràng để mô hình hóa lớp dữ liệu trong ứng dụng của bạn. Một khi đã định nghĩa  mô hinh dữ liệu, bạn có thể dễ dàng thực hiện các câu truy vấn cũng như cập nhật, xóa, sửa dữ liệu một cách hiệu quả.

Hi vọng những hướng dẫn và ví dụ mẫu ở trên đã giúp bạn làm quen với LINQ. Tôi sẽ tiếp tục các bài viết này để giúp bạn khám phá LINQ to SQL một cách chi tiết hơn.

Các bạn đang xem bài viết trong loạt bài “LINQ to SQL”, loạt bài này được dịch từ blog ScottGu http://weblogs.asp.net/scottgu/

Tagged with: , ,

74 phản hồi

Subscribe to comments with RSS.

  1. Khách said, on 24/10/2008 at 20:51

    When insert new record in C#, I can not use like your introduction :) .

    But I can use by this way

    db.Categories.InsertOnSubmit(category);

    Btw, thanks :)

  2. namdh said, on 27/10/2008 at 08:41

    there are two ways to insert a new record, the first way is you have to call InsertOnSubmit function as you did. The second way is you can simply add the new record to a collection of objects.
    I don’t know why you can not do it, but I can insert in both of these ways :D

  3. Khách said, on 27/10/2008 at 11:14

    Thanks bạn Nam Già nhiều lắm.Bạn đã làm 1 việc rất có ý nghĩa cho mọi người.
    Mình thấy BLog ScottGu rất hay.và những bài dịch của bạn cũng rất bổ ích.
    Chúc bạn sức khỏe!

  4. namdh said, on 29/10/2008 at 09:26

    He he, thanks

  5. Minh trí said, on 21/12/2008 at 08:46

    Bạn viết rất hay và kỹ.Nhưng thực ra các bạn có thể vào đây để xem các đoạn video và source code:
    http://asp.net
    Nhưng mình không hiểu
    vd:
    NorthwindDataContent db =new NorthwindDataContent();
    var products=from p in db.products
    select p;
    vậy mình muốn đưa từng giá trị của p vào các ô textbox thì mình phải làm như thế nào?

  6. namdh said, on 22/12/2008 at 10:04

    Vì kết quả trả về của câu truy vấn chứa trong biến products là một tập hợp, vậy nên nếu bạn muốn đưa vào các ô text box thì bạn phải chỉ ra dòng nào trong tập kết quả này.
    var products=from p in db.products select p;
    txtProductID.Text = products.ElementAt(i).ProductID;

    Hoặc nếu kết quả của bạn chắc chắn là một dòng thì bạn có thể dùng phương thức mở rộng Single() để lấy về dòng duy nhất đó.
    var product=(from p in db.products select p).Single();
    và sau đó viết txtProductID.Text = product.ProductID;

  7. HoangTuanSu said, on 22/12/2008 at 16:59

    Nam cho mình hỏi cái nữa, mình gặp phải vấn đề khi update. Nó cứ hiện ra thông báo là:
    Cannot add an entity with a key that is already in use.
    Trên mạng, nó có chỉ là phải set null cái DataContext, rồi tạo cái DataContext mới và dùng lệnh:

    newDc.[Entitys].Attach(newEntity, true);
    nhưng mình vẫn không làm được.

    Không biết Nam và mọi người gặp phải trường hợp này chưa?

  8. namdh said, on 22/12/2008 at 17:37

    Thông báo trên có thể do bạn đã thêm một bản ghi với khóa đã tồn tại, trường hợp này chỉ có duy nhất một cách là bạn phải thay giá trị khóa khác để không bị trùng.
    Thêm nữa, nếu muốn tạo một đối tượng DataContext mới thì bạn chỉ cần new lại mà không cần đặt null trước, nhưng thực ra việc này có lẽ không giúp ích gì trong trường hợp này.

  9. HoangTuanSu said, on 23/12/2008 at 07:08

    Cái này là mình làm trong phần update. Xóa cái record rồi insert lại cái đó đã được chỉnh sửa thì ok. Còn update bình thường như đoạn code trên thì nó thông báo lỗi như vậy.

  10. namdh said, on 23/12/2008 at 09:20

    Bạn có thể gửi đoạn code đó lên đây được không ?

  11. mrtuan said, on 07/03/2009 at 16:50

    Cac ban oi minh la thanh vien moi. Minh moi bat dau tim hieu ve Linq to SQL. Minh thay luc goi doi tuong DataContext nhan vao 1 gia tri la String. Nhung minh chua hieu String nay duoc dung nhu the nao? No co phai la duong dan de luu file database khong? Lam sao de goi no? Giup minh voi. Thankyou

  12. namdh said, on 09/03/2009 at 10:05

    String đó chính là chuỗi “connection string” dùng để kết nối đến CSDL. Bạn có thể tham khảo chuỗi kết nối này trong các sách về ADO.NET để biết cách dùng chuỗi này.
    Riêng đối với LINQ to SQL bạn có thể dùng cú pháp sau: Server=;Database=;UserID=;Password=;Trusted_Connection=false;
    Trong đó:
    là tên máy chủ
    là tên CSDL
    là người dùng
    là mật khẩu

    (Chú ý là LINQ to SQL chỉ được dùng với SQL Server)

  13. nemo said, on 28/03/2009 at 14:29

    Bạn Nam ơi, cho mình hỏi tí nhé:
    Mình có 1 table là tblUser(username,password)
    Mình có 1 form gồm 2textbox là: txtusername và txtpassword. và thêm 1 button đăng nhập.Muốn kiểm tra dữ liệu người dùng nhập vào có đúng với 2 trường đó trong table hay ko thì phải viết đầy đủ như thế nào hả bạn?Mình mới học nên chưa nắm rõ lắm. Nhớ bạn chỉ giúp nha. Thanks….

  14. namdh said, on 29/03/2009 at 18:29

    Bạn có thể viết là:

    var c = (from user in context.tblUser where user.username = txtusername.Text and user.password = txtpassword.Text).Count();

    Nếu (c == 1) có nghĩa là có 1 cặp username/password khớp với thông tin đã nhập.

  15. NguyenDuc said, on 30/03/2009 at 14:15

    Cám ơn những bài dịch bổ ích và những câu trả lời nhiệt tình của anh Nam, chúc anh sức khỏe để còn tiếp tục giúp mọi người nha.

  16. Billle said, on 03/04/2009 at 17:02

    a Nam cho hỏi :
    trong câu lệnh : “2.Cập nhật một sản phẩm trong CSDL” nếu mà có 2 sản phẩm cùng tên thì sữa lại như thế nào?

  17. namdh said, on 04/04/2009 at 23:07

    Nếu vậy thì em phải lấy Product thông qua ID, kiểu như sau:

    Product product = db.Products.Single(p => p.ProductId == txtProductId.Text);

    Rồi sau đó đổi tên như bình thường

  18. sonkt said, on 15/04/2009 at 23:51

    Em chưa hiểu đoạn này:
    Product product = db.Products.Single(p => p.ProductId == txtProductId.Text);
    Cái p ở đây là gì, có phải khai báo hay không, và nó có tác dụng gì trong đoạn code này ạ.

  19. namdh said, on 16/04/2009 at 09:50

    Đây là một biểu thức lambda, viết như vậy có nghĩa mình đang khai báo một hàm anonymous có dạng:

    bool f(p)
    {
    return p.ProductId == txtProductId.Text;
    }

    Biểu thức lambda rất hay được dùng với LINQ, vì nó giúp code gọn gàng hơn, thay vì phải khai báo một hàm, rồi truyền delegate đến hàm đó vào cho câu lệnh Single, ta có thể viết trực tiếp kiểu như trên luôn.

  20. myway said, on 13/05/2009 at 10:29

    dùng Linq với Linq to sql có gì khác nhau.Mình mới tìm hiểu,mong các bạn giúp đỡ

  21. myway said, on 13/05/2009 at 10:35

    anh Nam ơi!cho em hỏi mình dùng StoreProceduce trong Linq như thế nào?Tại sao em không thấy cái Sto nào trong khung explore server?Mong anh giúp em sớm

  22. namdh said, on 13/05/2009 at 11:03

    LINQ là một thành phần trong .NET cho phép bạn có thể viết các câu lệnh theo kiểu truy vấn ngay trong mã nguồn C#, VB (hay các ngôn ngữ được hỗ trợ trên .NET khác), các câu lệnh truy vấn này cho phép bạn làm việc dễ dàng với các tập hợp dữ liệu như array, list… hoặc cả các cấu trúc phức tạp hơn như XML và dữ liệu quan hệ trong 1 cơ sở dữ liệu.
    LINQ được cấu thành từ nhiều thành phần, và kiến trúc mở của nó cho phép nhà phát triển có thể xây dựng các thành phần mới dùng LINQ để truy vấn vào các nguồn dữ liệu khác. Mỗi một kiểu thành phần truy cập nguồn dữ liệu sẽ được đặt 1 cái tên như LINQ to Objects, LINQ to XML hay LINQ to SQL (chuyên dùng để truy cập vào dữ liệu trong CSDL SQL Server).

  23. namdh said, on 13/05/2009 at 11:04

    Nếu trong khung Server Explorer không có Stored Proc thì có nghĩa là em chưa có cái nào, em phải tạo mới trước khi dùng.

  24. myway said, on 15/05/2009 at 09:28

    mình phải tạo nó như thế nào hả anh Nam. Em mới tìm hiểu nên cũng không rõ lắm, anh giúp em với nhé.Cảm ơn anh nhièu

  25. vodanh said, on 20/05/2009 at 10:19

    làm cách nào để gọi được lệnh northwind.SubmitChanges();trong linq to sql
    bạn nào biết giúp mình với!

  26. namdh said, on 20/05/2009 at 15:27

    Bạn phải tạo một biến DataContext có tên northwind, trong các ví dụ ở bài trên thì biến này được đặt tên là db. Bạn chắc chắn đã phải có biến này rồi vì bạn bắt buộc thông qua nó để thực hiện truy vấn/cập nhật dữ liệu (nếu chưa thì gọi SubmitChanges để làm gì :) )

  27. Thtt said, on 29/05/2009 at 14:26

    a cho em hỏi là tại sao khi duyệt qua tất cả các phần tử của một DataContext và lấy ra text của từng element (x.ElementAt(i).Text) khi chạy ctr lại báo là không support cái ElementAt??? Khi insert em cũng làm đúng như anh làm và ko có lỗi j xảy ra cả nhưng dữ liệu vẫn “trơ trơ” ko chịu vào csdl là sao anh nhỉ?

  28. namdh said, on 30/05/2009 at 10:30

    - DataContext không phải một tập hợp thì làm sao em có thể duyệt qua từng phần tử được ?
    - Sau khi gọi InsertOnSubmit, nếu muốn dữ liệu được đưa thực sự vào CSDL thì em phải gọi SubmitChanges() trong lớp DataContext.

  29. văn đạo said, on 04/06/2009 at 20:51

    Anh Nam cho em hỏi giả sử em viết một câu truy vấn linq đơn giản trong tầng DataAccess chẳng hạn như:

    DataClasses1DataContext db = new DataClasses1DataContext();
    var p = from a in db.nviens
    select a;

    thì em phải trả về kiểu dữ liệu là gì để bên tầng giao diện em có thể gán nó vào một control ví dụ như dataGridView. Cám ơn anh nhiều.

  30. sON said, on 08/06/2009 at 14:41

    Ban co the convert ket qua tra ve thanh` 1 arrayList cac nvien roi dua vao datagridview

  31. Son said, on 08/06/2009 at 15:31

    Hi a.Nam, cho tôi hỏi: khi mình tạo 1 Datacontext, Khi mà trong database minh co thay đổi, vd như tên column, tên table, hoặc liên kết table, thi minh phải tạo lai DataContext, và phải sửa lại tất cả code LINQ? làm như vậy nếu đã code n` rồi thì sửa rất là phức tạp. có cách nào khác ko ?

  32. pvt said, on 08/06/2009 at 21:19

    Anh Nam cho em hỏi chút.
    Em đang thử dùng LINQ. Nhưng khi em lấy một dòng trong một tập hợp như sau:

    MessageBox.Show(products.ElementAt(0).ProductName);
    thì chương trình lại báo lỗi là “Query operator ‘ElementAt’ is not supported’”
    Em chuyển nó thành
    products.toList().ElementAt(0).ProductName
    thì lại được.

  33. namdh said, on 08/06/2009 at 23:32

    @văn đạo: Cảm ơn bạn Son đã trả lời giúp, ngoài ra nếu anh nhớ không lầm thì nhiều control cũng hỗ trợ các LINQ data table hoặc query, do vậy em có thể gán luôn biến p vào cho DataSource cũng được.

  34. namdh said, on 08/06/2009 at 23:33

    @Son: tất nhiên rồi bạn ạ, tuy nhiên dùng LINQ to SQL có lợi ở chỗ khi tạo lại data model xong, trình dịch sẽ phát hiện được ngay các câu truy vấn nào cần phải sưa lại cho bạn.

  35. namdh said, on 08/06/2009 at 23:35

    @pvt: Vì products của em thực chất là một câu query, do vậy nó không hỗ trợ ElementAt (cũng như em không thể dùng elementAt trên một tập kết quả SELECT vậy).

  36. văn đạo said, on 09/06/2009 at 21:06

    Em có một câu hỏi nhỏ là tại sao biến “var” em đánh trong class thì không hiểu mà trong win form lại hiểu. Cám ơn anh

  37. namdh said, on 11/06/2009 at 14:19

    var là từ khóa được dùng để khai báo một biến có kiểu do trình dịch tự xác định, và chỉ được dùng khi khai báo các biến local, tức là bên trong các phương thức – và không phụ thuộc phương thức đó thuộc một lớp winform hay một lớp bình thường khác.

  38. Scorpion said, on 25/06/2009 at 10:32

    Khi thiết kế DBML, nếu có 2 class có ràng buộc với nhau (Product và Category chẳng hạn), thì tại WCFService khi muốn lấy toàn bộ dữ liệu của Product (trả ra kiểu list) không được.
    VD:
    public List GetAllProduct()
    {
    NorthwindDataContext db = new NorthwindDataContext ();
    var product = from p in db.Products
    select p;
    return product.ToList();
    }

    Nhưng nếu 2 class đó là Product và Customer (không có ràng buộc) thì lại lấy được? Vậy là sao, mong các cao thủ chỉ giáo.

  39. namdh said, on 25/06/2009 at 14:49

    Chào bạn, nguyên nhân gây ra lỗi trên là do việc nạp dữ liệu xoay vòng. Khi gọi ToList(), các Product sẽ load các Category tương ứng, rồi các Category lại nạp tiếp các Product tương ứng, điều này sẽ gây lỗi và service sẽ đóng kết nối.
    Để giải quyết vấn đề này, bạn phải chỉnh lại thuộc tính Serialization Mode của mô hình dữ liệu thành Unidirectional (mặc nhiên là None). Chế độ Serialization này chỉ thực hiện việc “serializing” từ lớp cha sang lớp con mà không làm ngược lại (*). Ngoài ra, bạn cũng phải yêu cầu LINQ to SQL nạp các đối tượng con khi thực hiện truy vấn:

    NorthwindDataContext context = new NorthwindDataContext();
    System.Data.Linq.DataLoadOptions dlo = new System.Data.Linq.DataLoadOptions();
    dlo.LoadWith(e => e.Product);
    context.LoadOptions = dlo;

    var category = from c in db.Categories
    select c;
    return category.ToList();

    (*) Vì tính chất này nên bạn phải lấy Category và con của nó (Product) thay vì lấy các Product như bạn làm.
    Bạn có thể tham khảo thêm về vấn đề này tại đây: http://www.codeexperiment.com/post/Returning-LINQ-to-SQL-Entities-From-WCF.aspx

  40. Scorpion said, on 26/06/2009 at 09:35

    Cám ơn NamDH!

    Mình thử chuyển thuộc tính Serialization Mode = Unidirectional thì được luôn, mà không phải viết lại LINQ.
    Từ trước tới giờ mình quen thao tác với dữ liệu thông qua DataSet, giờ Silverlight không đọc được DataSet trả về từ WCFService, nên cũng hơi khó khăn, phải bắt đầu với LINQ.
    Cậu có tài liệu hướng dẫn bắt đầu với LINQ không, ý nghĩa của các câu lệnh ấy. Đơn giản như câu lệnh này e => e.Product mình cũng chưa hiểu.:D
    Quen với SQL Query rồi.

  41. Scorpion said, on 26/06/2009 at 10:52

    Mình có muốn hỏi mấy vấn đề nữa :D
    - Giả sử mình muốn trả ra List chỉ gồm có ProductID, ProductName, CategoryName thì mình phải viết thế nào? Lúc mình trả ra toàn bộ (như kiểu SELECT *) thì được, nhưng khi select new {p.ProductName}, rồi return product.ToList() thì báo lỗi.
    - Khi có List như vậy rồi, mình muốn Bind một Column cụ thể vào TextBox như thế nào.
    Như DataSet ngày xưa thì là:
    TextBox1.Text = DataSetName.Tables[0].Rows[0]["COLUMN_NAME"].ToString();

  42. namdh said, on 26/06/2009 at 13:26

    Bạn có thể tham khảo sách LINQ tại đây: http://namdh.wordpress.com/2008/07/28/linq-book/
    Còn câu e => e.Products ở trên thì nó tương tự như việc khai báo một hàm có dạng:
    function f(e)
    {
    return e.Product;
    }
    Đây là một biểu thức lambda được giới thiệu cùng LINQ, và cũng là một phần “gần như” không thể thiếu khi dùng LINQ (vì vẫn có thể không dùng như sẽ mất công hơn nhiều).

  43. namdh said, on 26/06/2009 at 13:39

    Bạn nói rõ lỗi gặp khi gọi toList() được không ?

  44. Scorpion said, on 26/06/2009 at 14:24

    http://yfrog.com/3×24156181j

  45. Scorpion said, on 26/06/2009 at 14:27

    Ý mình là muốn join 2 bảng Product và Category để lấy Tên sản phẩm, Tên Nhóm sản phẩm chẳng hạn
    Bạn có thể giúp mình viết phần đó được không? Và cả cách đưa dữ liệu ra 1 Control nữa
    Kiểu như thế này:
    - Khi có List như vậy rồi, mình muốn Bind một Column cụ thể vào TextBox như thế nào.
    Như DataSet ngày xưa thì là:
    TextBox1.Text = DataSetName.Tables[0].Rows[0]["COLUMN_NAME"].ToString();

  46. Scorpion said, on 26/06/2009 at 14:34

    public List GetAllCategories()
    {
    TAIKHOANDataContext db = new TAIKHOANDataContext();
    var product = from p in db.Products
    select new
    {
    p.Category.CategoryName,
    p.ProductName
    };
    return product.ToList();
    }

    Error:
    1) Error 1 Instance argument: cannot convert from ‘System.Linq.IQueryable’ to ‘System.Collections.Generic.IEnumerable’ D:\ASPNet\SilverLight_Login\MyWebService\TAI_KHOAN_SERVICE.svc.cs 54 20 MyWebService
    2) Error 2 ‘System.Linq.IQueryable’ does not contain a definition for ‘ToList’ and the best extension method overload ‘System.Linq.Enumerable.ToList(System.Collections.Generic.IEnumerable)’ has some invalid arguments D:\ASPNet\SilverLight_Login\MyWebService\TAI_KHOAN_SERVICE.svc.cs 54 20 MyWebService

  47. Scorpion said, on 29/06/2009 at 09:42

    Alo, đồng chí NamDH đâu rồi, support cho mình mấy câu hỏi này đi, nghiên cứu mãi mà không ra.

  48. namdh said, on 29/06/2009 at 10:57

    Vì không có chương trình của bạn nên mình khó biết chính xác lỗi gì, nhưng theo thông báo thì có thể nó không thể dùng ToList cho một lớp anonymous (được tạo bởi câu select new
    {
    p.Category.CategoryName,
    p.ProductName
    };)

    Bạn hãy thử dùng một lớp cụ thể xem sao, ví dụ, bạn có thể tạo một lớp như sau:

    class ProductInfo {
    public ProductInfo(string pn, string cn) {
    this.ProductName = pn;
    this.CategoryName = cn;
    }
    public ProductName()
    { get; set; }
    public CategoryName()
    { get; set; }
    }

    Câu truy vấn sẽ được viết lại như sau:
    var product = from p in db.Products
    select new ProductInfo
    {
    p.ProductName,
    p.Category.CategoryName
    };

    Kiểu trả về của hàm sẽ là:
    public List<ProductInfo> GetAllCategories()

    Bạn thử lại xem, nếu vẫn còn lỗi thì tốt nhất bạn gửi cả project lại đây :)

  49. namdh said, on 29/06/2009 at 11:20

    Bạn gán giá trị vào TextBox như sau:
    TextBox1.Text = myQuery.ElementAt(0).ProductName;

  50. Scorpion said, on 29/06/2009 at 12:01

    Code của mình đây: http://www.mediafire.com/download.php?ymmwxnz5dqm
    Bạn xem lại code giúp mình với nhé. Chạy bắt đầu từ trang Default.aspx, không cần phải gõ Username và Password. Database là Northwind.

    Mình không gán trực tiếp giá trị vào TextBox ngay trong hàm đó, nên không thể lấy myQuery được.
    Ở ví dụ của mình, tại trang DanhSachKhachHang.xaml, mình có 1 TextBox chẳng hạn, sau khi mình lấy được 1 List Product, mình muốn bind tên product đó vào textbox thì làm thế nào.

    Cám ơn bạn rất nhiều!

  51. tmp said, on 30/06/2009 at 19:28

    Ví dụ như mình có 2 bảng HocSinh(MaHS,HoTen,MaLop) và Lop(MaLop,TenLop)
    Mình truy vấn như sau:
    from hs in context.HocSinhs
    from l in context.Lops
    where hs.MaLop == l.MaLop
    select new
    {
    hs.MaHS,hs.HoTen,hs.DiaChi,l.TenLop
    }
    Khi show lên DataGridView thì dữ liệu trong Grid ở dạng readonly. Cho mình hỏi làm cách nào để modify dữ liệu trên Grid vừa show ra ?

  52. Scorpion said, on 02/07/2009 at 15:13

    Bác chủ Topic đang đi nghỉ mát :D

  53. Scorpion said, on 07/07/2009 at 09:28

    Alo, bác chủ topic đâu rồi, help me.

    Thế này thì chạy OK

    public List GetAllCategories()
    {
    TAIKHOANDataContext db = new TAIKHOANDataContext();
    var product = from p in db.Products
    select p;
    return product.ToList();
    }

    Thế này thì báo lỗi:
    public List GetAllCategories()
    {
    TAIKHOANDataContext db = new TAIKHOANDataContext();
    var product = from p in db.Products
    select p.ProductName;
    return product.ToList();
    }

  54. Scorpion said, on 07/07/2009 at 09:30

    Quên, hàm trả ra kiểu List nhé!

  55. Scorpion said, on 07/07/2009 at 09:59

    Trả ra kiểu List

  56. namdh said, on 15/07/2009 at 14:24

    Chà, mấy ngày này bận quá nên không trả lời “hộp thư truyền hình” được, sorry các bạn.

    Ban ngày làm việc ở công ty, rồi lại đón con, chăm con (2 vợ chồng phải chăm 2 nhóc), chuẩn bị ra mắt phiên bản kế tiếp của StockViewer, hoàn thành những bước cuối cùng về kỹ thuật của 1 webgame, chuẩn bị các thủ tục để mở công ty, thử nghiệm các tính năng của Android và Silverlight mới, tập tành viết ứng dụng cho N97…
    Giải quyết các nhiệm vụ trong Rainbow Six, xong rồi chuyển sang Call ỏ Duty 4 (đã xử lý xong thằng 5 rồi) :D .

  57. Khiếu Trung Sơn said, on 15/07/2009 at 14:38

    Thầy mở công ty ạ. Công ty về lĩnh vực gì ạ. Chắc là cung cấp webgame. :) ) E đoán thế. Bận thế lại còn call of duty. Thầy chia time kiểu gì mà tài quá. Thật là ngưỡng mộ. Chia sẻ cho em với.

  58. namdh said, on 15/07/2009 at 14:41

    Trời, mới post xong đã có reply rồi, nhanh quá. Thật là ngưỡng mộ.

  59. namdh said, on 15/07/2009 at 14:45

    Thực ra thì dù thời gian có eo hẹp đến đâu thì cũng cần phải để lại chút ít để relax, đó là lúc tái tạo sức lại động mà, có thể nghỉ ngơi, nghe nhạc, hoặc làm điều gì mình thích (chơi game :D ). Nghỉ ngơi cũng là cách làm việc hiệu quả mà.

  60. Scorpion said, on 15/07/2009 at 17:40

    Có việc muốn hỏi tiếp ông bạn đấy :D Chờ nhé!

  61. namdh said, on 16/07/2009 at 15:36

    Hix, sợ quá :D

  62. Nguyễn Thị Lương said, on 12/08/2009 at 02:17

    Anh Nam ơi, em bây giờ muốn tìm hiểu về LinQ vậy anh có thể cho em một ví dụ đơn giản trên winform có sử dụng LInQ được ko? Em đang rất cần. Em cảm ơn anh nhiều.
    Em mong sớm nhận được phản hồi của anh!

  63. Nguyễn Thị Lương said, on 12/08/2009 at 02:28

    Cả nhà mình có ai tìm hiểu trên Winform rồi thì chỉ giáo giúp mình nhé. Cảm ơn mọi người nhiều1

  64. namdh said, on 12/08/2009 at 09:16

    LINQ thì dù có dùng trên ASP.NET hay dùng trong Windows Form thì cũng như nhau thôi em ạ.
    Nếu em đã từng dùng ADO.NET rồi thì cứ thế mà áp dụng vào cho LINQ thôi :)

  65. karakifun said, on 21/08/2009 at 15:48

    DataClasses1DataContext bdd = new DataClasses1DataContext();
    IEnumerable acc = bdd.pro_login(txt_User.Text, txt_Pass.Text);
    //var acc = bdd.pro_login(txt_User.Text,txt_Pass.Text )

    if (acc.Count()!=0)
    {
    foreach (account item in acc)
    {
    if (item.isadmin.Value==true)
    {
    Response.Redirect(“insert.aspx”);
    }
    else
    {
    Response.Redirect(“welcome.aspx”);
    }
    }

    }
    else
    {
    lbl_ThongBao.Text = “Tài khoản hoặc mật khẩu không đúng!!!”;
    txt_User.Focus();
    }

    em viet nhu the nhung no lai bao loi, yeu cau cua e la , neu la thanh vien dang nhap thi cho vao trang welcome, neu thanh vien la admin thi cho vao trang insert, con neu sai tai khoan,thi xuat hien thong bao, nhung e viet nhu the, no lai bao loi la “The query results cannot be enumerated more than once. ” khi e nhap thong tin ve tai khoan dung.

  66. karakifun said, on 21/08/2009 at 15:50

    bo sung chut, pro_login la store nhe, isadmin la 1 cot trong bang csdl kieu bit(true/false)

  67. namdh said, on 21/08/2009 at 16:19

    em không thể enum một query 2 lần (1 lần trong count). với đoạn code trên thì em có thể viết:

    bool found = false;
    foreach (account item in acc)
    {
    if (item.isadmin.Value)
    {
    Response.Redirect(”insert.aspx”);
    }
    else
    {
    Response.Redirect(”welcome.aspx”);
    }

    found = true;
    }

    if (!found)
    {
    lbl_ThongBao.Text = “Tài khoản hoặc mật khẩu không đúng!!!”;
    txt_User.Focus();
    }

    nhưng nếu dùng SP thì cách trả kết quả như vậy có vẻ không hiệu quả, em nên kiểm tra ngay bên trong thủ tục và sau đó trả về mã kết quả (0 = not found, 1 = normal user, 2 = admin…) thì hay hơn.

  68. karakifun said, on 21/08/2009 at 16:48

    SP của em giống vầy
    “ALTER PROCEDURE pro_login
    @user varchar(20),
    @pass varchar(10)
    AS
    select * from accounts
    where username=@user and pass=@pass

    return @user,@pass”

    giờ sửa như thế nào cho giống ý anh, hi, em ngốc lắm, phiền a chút nha

  69. namdh said, on 21/08/2009 at 17:32

    em viết giống như sau:
    ALTER PROCEDURE pro_login
    @user varchar(20),
    @pass varchar(10)
    AS
    DECLARE @isadmin BIT

    select @isadmin = isadmin from accounts
    where username=@user and pass=@pass

    IF @isadmin IS NULL
    RETURN 0
    ELSE
    IF @isadmin = 0
    RETURN 1
    ELSE
    RETURN 2
    GO

    Anh viết chay thôi, em về test và sửa lại cho chạy nhé.

  70. ngocchau_nb2005 said, on 19/09/2009 at 16:47

    Nhưng các anh chị ơi cho em hỏi là:những câu truy vấn trên chúng ta viết vào đâu vậy ạh.ví dụ như em muốn hiển thị dữ liệu len một listbox thì phải viết các câu truy vấn trên vào chỗ nào.
    Chỉ dùm em với.

  71. YoonA said, on 16/10/2009 at 16:00

    Cho mình hỏi tí nhé:
    Mình có 1 table là login(userid,pass,role)
    Mình có 1 form gồm 3textbox là: txtTK, txtMK,txtrole và 1 datagridview
    Mình muốn là khi click vào bất kì 1 cell trong DataGridView thì sẽ xuất hiện userid lên txtTK
    Giúp mình nha.ty

  72. KidKid said, on 18/10/2009 at 21:48

    Hi anh,
    Lâu quá không gặp, hi vọng anh vẫn “phong độ” như ngày nào.

    Có một vài câu hỏi định send private cho anh, nhưng mà ko tìm được email. Đành spam ở đây vậy :)

    1. Em định trích dẫn bài viết của anh ở trang web riêng, vậy hi vọng anh cho phép, đó cũng là một cách để chia sẻ cho mọi người phải không anh ?

    2. Em đang định viết bài về LinQ trong mô hình 3 lớp … Nếu anh đã có kinh nghiệm thì hi vọng anh góp ý cho em tham khảo.

    Cảm ơn anh :)

  73. namdh said, on 29/10/2009 at 09:57

    He he, dạo này bận quá nên hết “phong độ” rồi :)

    1. Em có thể trích dẫn các bài viết trên blog của anh. Tất cả các bài viết trên blog của anh đều có thể đăng lại mà không cần hỏi ý kiến anh, thậm chí có thể không cần đăng tên tác giả, tuy nhiên nếu đã đăng tên thì hi vọng đó sẽ là tên anh :) ).

    2. Ok, việc đầu tiên phải là viết các đã, rồi anh mới góp ý được.

  74. Trần Mạnh Tùng said, on 10/11/2009 at 11:21

    LINQ and SQL, công nghệ mới này là mình không cần phải viết các thủ tục trong store procedure của sql nữa phải không Anh. Mình chỉ việc sử dụng công nghệ này là ok rồi phải không.

    Vì hông hiểu nên hỏi, mong anh chỉ cho


Để lại hồi âm