2011-10-20 27 views
14

tôi dường như viết này khá nhiều trong mã của tôi:Enforce chỉ hàng duy nhất trở về từ DataReader

using (var reader = cmd.ExecuteReader()) 
{ 
    if (reader.Read()) 
    { 
     result = new User((int)reader["UserId"], reader["UserName"].ToString()); 
    } 

    if (reader.Read()) 
    { 
     throw new DataException("multiple rows returned from query"); 
    } 
} 

Có một số được xây dựng theo cách để làm điều này mà tôi không biết?

+3

Có lẽ nếu bạn có quyền kiểm soát các truy vấn, bạn có thể làm một 'TOP 1' trong nó .. Nếu bạn muốn kiểm tra tính toàn vẹn của cơ sở dữ liệu, có lẽ bạn nên đặt một 'UNIQUE INDEX' so với các cột trong câu lệnh' WHERE' của bạn thay vì làm điều này. –

+1

Điều gì về việc thêm TOP 1 vào truy vấn sql của bạn? – Stecya

+4

Tôi không muốn TOP 1, tôi muốn có ngoại lệ. Họ không giống nhau chút nào. – fearofawhackplanet

Trả lời

15

Tôi không biết, nhưng mã này có thể được phân thành một phương pháp khuyến nông:

public static R Single<R>(this DataReader reader, Func<DataReader,R> selector) { 
    R result = default(R); 
    if (reader.Read()) 
     result = selector(reader); 
    if (reader.Read()) 
     throw new DataException("multiple rows returned from query"); 
    return result; 
} 

sẽ được sử dụng như thế:

using (var reader = cmd.ExecuteReader()) 
{ 
    User u = reader.Single(r => new User((int)r["UserId"], r["UserName"].ToString())) 
} 

Tiết kiệm bạn khỏi sự trùng lặp mã.

+0

Chúng ta có thể tránh mã trùng lặp nhiều hơn bằng cách tạo một phương thức mở rộng cho 'SqlCommand'. 'User u = cmd.Single (...);' –

+0

Chắc chắn, trên API cấp thấp đó, với một vài phương pháp mở rộng, bạn có thể định hình nó thành những thứ khá hữu ích :) – flq

+0

Tôi không thích phần mở rộng trên 'SqlCommand' rất nhiều bởi vì nó không thực hiện bất kỳ giao diện hữu ích nào. – fearofawhackplanet

1

Nếu bạn đang sử dụng sql để tìm dữ liệu của mình, điều này có thể giúp bạn bằng cách cho phép bạn xóa loại mã hóa đó trong mọi trường hợp mà bạn cần sử dụng trình đọc dữ liệu.

SELECT TOP ([Number of rows you want to be selected]) 
FROM [Table Name] 
WHERE [Condition] 

EX:

SELECT TOP (1) 
FROM tblUsers 
WHERE Username = 'Allan Chua' 

Một sử dụng mũi thủ tục lưu trữ, sử dụng chúng có thể giảm thiểu sự lặp lại của truy vấn SQL và mã hóa không cần thiết.

8

Điều này có thể hoặc có thể không giúp tùy thuộc vào mục tiêu của bạn. Nếu bạn cần phát hiện ra rằng nhiều hàng đã được trả lại để ném một ngoại lệ thích hợp, thì điều này sẽ không giúp ích gì.

Nếu bạn chỉ muốn đảm bảo rằng chỉ có một kết quả được trả lại, bạn có thể có khả năng gặp phải tình trạng hoạt động bằng cách sử dụng phương pháp này. Từ những gì tôi hiểu, các nhà cung cấp dữ liệu có thể sử dụng điều này để tối ưu hóa truy vấn với dự đoán một kết quả hàng đơn.

Trong mọi trường hợp, những gì bạn sẽ muốn làm là sử dụng SqlCommand.ExecuteReader để tạo trình đọc dữ liệu của bạn, nhưng chuyển một đối số từ liệt kê CommandBehavior (cụ thể là CommandBehavior.SingleRow). ExecuteReader bị quá tải để chấp nhận điều này.

CommandBehavior enum

SqlCommand.ExecuteReader overload

Vì vậy, mã của bạn có thể trông như thế này:

using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) 
{ 
    if (reader.Read()) 
    { 
     result = new User((int)reader["UserId"], reader["UserName"].ToString()); 
    } 
} 
Các vấn đề liên quan