Đào Hải Nam

Lấy các dòng ngẫu nhiên (LINQ tip #3)

Posted in Microsoft .NET by namdh on 27/11/2008

Trong SQL Server, để lấy về một tập kết quả ngẫu nhiên, bạn có thể viết:

SELECT TOP 5 * FROM myTable ORDER BY NEWID()

Trong LINQ, nếu muốn lấy về một tập kết quả ngẫu nhiên kiểu như trên, bạn cần tạo một hàm ngẫu nhiên, sau đó thêm nó vào LINQ designer, và dùng hàm đã tạo để sắp xếp. Các bước cụ thể như sau:

Tạo một SQL Server Project:

new_sql_project

Thêm vào một user-defined function có tên RandomInt, đây là một hàm CLR chạy trong CSDL:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunctions
{
private readonly static Random r = new Random();   
    [Microsoft.SqlServer.Server.SqlFunction] 
    public static SqlInt32 RandomInt()
    {
        return r.Next();
    }
};

Sau đó, bạn bấm nút phải vào SQL Server Project vừa tạo và chọn Deploy:

linq_tip3_deploy_project

và kéo hàm này từ cửa sổ Server Explorer vào LINQ Designer:

linq_tip3_dnd_function

Sau khi kéo thả, bạn sẽ thấy hàm này xuất hiện tren MethodPane của cửa sổ LINQ Designer:

sql_randomint

Và có thể dùng nó trong câu lệnh lấy dữ liệu ngẫu nhiên như sau:

DataClasses1DataContext _context = new DataClasses1DataContext();
var s = (from c in _context.mytable orderby _context.RandomInt() select c).Take(5);

Khi đó, s sẽ chứa 5 dòng ngẫu nhiên từ CSDL (theo thứ tự ngẫu nhiên).

Tagged with: ,

10 phản hồi

Subscribe to comments with RSS.

  1. Kevin said, on 27/11/2008 at 19:09

    Trường hợp xài SQL 2k (không hỗ trợ tạo SQL Server Project) thì sao ạh?

  2. namdh said, on 28/11/2008 at 08:44

    Trời, vậy là làm khó nhau rồi :D . Chắc vào thời điểm này, không có dự án mới nào sử dụng LINQ (của năm 2008) trên SQL 2000 (của năm 2000) đâu nhỉ?
    Theo tôi đoán (chưa kiểm tra) nếu dùng LINQ trên SQL 2000 bạn cũng không thể dùng Skip() được vì hàm này sử dụng hàm ROW_NUMBER, vốn chỉ có từ SQL Server 2005.

  3. Kevin said, on 29/11/2008 at 16:25

    Hết rồi hả thầy :(

  4. namdh said, on 29/11/2008 at 16:27

    Hết gì cơ ???

  5. Kevin said, on 01/12/2008 at 12:16

    [quote]Sau đó, bạn Deploy và kéo hàm này từ cửa sổ Server Explorer vào LINQ Designer:[/quote]

    Dòng này nghĩa là sao vậy thầy?

  6. namdh said, on 01/12/2008 at 13:31

    Vừa cập nhật kỹ hơn, em xem lại nhé.
    Nếu ai có kinh nghiệm để làm điều này với LINQ trên các phiên bản cũ hơn SQL 2005 thì xin hãy chia sẻ luôn nhé. Thanks.

  7. Kevin said, on 01/12/2008 at 16:11

    Nó bảo em enable CLR mà em truy vấn:

    EXEC sp_CONFIGURE ‘clr enabled’ , ‘1′
    GO
    RECONFIGURE WITH OVERRIDE;
    GO

    Nó debug hoài không xong. Không hiểu tại sao.
    Thầy enable CLR làm sao vậy ạh?

  8. Kevin said, on 01/12/2008 at 16:21

    Àh OK được rồi ạh.
    Execute nó lâu wá em tưởng nó treo

  9. [potay]-com said, on 09/05/2009 at 05:49

    Chào anh Nam, nhờ anh giúp em chuyển câu truy vấn này sang LINQ nha! em cảm ơn anh rất nhiều:

    SELECT *
    FROM tbSanPham sp, tbHinhanh ha
    WHERE sp.ma_sp == ha.ma_sp
    AND sp.ma_sp=’SP001′

    Em đang làm LinQ mà không biết truy vấn như thế nào, mong anh giúp em.

  10. namdh said, on 12/05/2009 at 16:22

    @[potay]-com:
    Giả sử: đặt tên biến DataContext là ctx, em có thể dùng câu lệnh join để kết hợp từ 2 bảng, rồi trả về tập kết quả như sau:


    class SP
    {
    public SP(tbSanpham sp, tbHinhanh ha)
    {
    this.sp = sp;
    this.ha = ha;
    }
    ...
    }
    ...
    var sps = from sp in ctx.tbSanpham inner join ha in ctx.tbHinhanh on sp.masp equals ha.masp where sp.masp = "SP001" select new SP(sp, ha);

    Khi đó nếu muốn truy cập vào từng kết quả, em có thể viết:
    SP sp = sps.Single();
    print(sp.Sp.Tensanpham);


Để lại hồi âm