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


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).

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

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

  2. 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. [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?

  4. 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.

  5. 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?

  6. 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.

  7. @[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);

  8. Anh Nam!
    Sao em thử viết hàm RandomInt() theo anh thì bị lỗi như vậy.Em mới tập viết nên không biết như thế nào nữa.

    “Execution of user code in the .NET Framework is disabled. Enable “clr enabled” configuration option.”

  9. Lỗi này là do CSDL của em chưa cho phép sử dụng các thủ tục CLR, em phải chạy các câu lệnh sau để cho phép điều này:

    EXECUTE sp_configure ‘clr enabled’, 1
    RECONFIGURE

  10. Anh Nam ơi! Chỉ dùm e cách join mà viết tắt của LINQ như sau. VD em có 2 table Tinhs và Huyens, trong đó Tinhs có khóa ngoại là matinh. E tiến hành join như sau:
    Dưới đây là câu lệnh insert: context em đặt là ct nhé
    Khachhang k = new Khachhang();
    {
    k.huyen = (from p in ct.Huyens
    from c in ct.Tinhs
    where p.matinh==c.matinh
    where p.tenhuyen == huyen && c.tentinh == tinh
    select p.mahuyen).Single();
    }
    Anh Nam xem e có truy vấn sai ko? Nếu không sai thì anh chuyển nó về dùm kiểu truy vấn rút gọn dùm em có dạng:
    VD k.huyen = ct.Huyens.Where(p=> p.tenhuyen == huyen).select(p=>p.mahuyen).Single();
    Mong Anh chỉ giúp!

  11. Em chào anh! em cũng làm 1 cái UserDefinedFunctions như anh hướng dẫn ở trên. Nhưng khi em deploy thì không có cái function nào trong để kéo thả như anh noi! anh có thể giúp em dc ko? em dùng VS 2010. FW 4 và sql server 2005. Cảm ơn anh nhiều

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s