Câu hỏi Chỉ khóa nếu giá trị giống nhau?


Nếu tôi có một chức năng chỉnh sửa cơ sở dữ liệu trong dịch vụ web của tôi, tôi chỉ muốn một luồng thực hiện cùng một lúc nếu chúng cố chỉnh sửa cùng một hàng.

void EditCheck(long checkid)
    {

        if (isCheckCosed)
            throw new Exception("check is already closed");

        //do stuff

        //after i edit my check i want to close it.
        CloseCheck();
    }

tôi biết tôi có thể khóa toàn bộ chức năng, nhưng sau đó tôi mất preformance bởi vì hầu như không bao giờ các chủ đề khác nhau của nó sẽ cố gắng chỉnh sửa cùng một kiểm tra.

là có một cách để chỉ khóa ra các chủ đề khác có cùng một checkid?

CẬP NHẬT

tôi sử dụng OleDbConnection và MySqlConnection

OleDbCommand oleDbCommand = AccessTrans != null ?
new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn); 
oleDbCommand.ExecuteNonQuery();

chức năng tương tự cho MySqlCommand

và sau đó tôi sử dụng lệnh SQL bình thường INSERT và UPDATE. và giao dịch được kiểm tra nếu nó có mặt hay không. vì vậy chức năng này hoạt động nếu bạn muốn có một giao dịch hay không trong chức năng cấp trên của bạn.

để đọc từ cơ sở dữ liệu tôi sẽ điền DataTable

OleDbCommand oleDbCommand = AccessTrans != null ? new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn);
OleDbDataAdapter dAdapter = new OleDbDataAdapter();
dAdapter.SelectCommand = oleDbCommand;
dAdapter.Fill(dTable);
return dTable;

7
2017-09-25 15:21


gốc


Không nên điều này được xử lý trên cơ sở dữ liệu kết thúc? Bạn có thực sự có một vấn đề hoặc điều này chỉ dựa trên các giả định? - Kyle C
Quyền truy cập dữ liệu được viết như thế nào? Nếu bạn đang sử dụng EF, điều này có thể hữu ích:blogs.msdn.com/b/alexj/archive/2009/05/20/… - Lev
Bạn có thể chỉ ra cách bạn đang truy cập cơ sở dữ liệu, có những công cụ tốt được xây dựng trong nhiều phương thức truy cập dữ liệu để xử lý vấn đề này (bất kỳ giải pháp nào xảy ra phía máy khách sẽ chỉ hoạt động nếu chỉ có một máy khách kết nối với cơ sở dữ liệu. chương trình cả hai cuộc gọi EditCheck cho cùng checkid các câu trả lời hiện tại sẽ không hoạt động) - Scott Chamberlain
@ScottChamberlain đã cập nhật câu hỏi của tôi để bao gồm mã cơ sở dữ liệu. - Dendei


Các câu trả lời:


Bạn có thể sử dụng ConcurrentDictionary để ánh xạ từng id tới một đối tượng mà bạn có thể khóa trên:

public class Foo
{
    private ConcurrentDictionary<long, object> dictionary = 
        new ConcurrentDictionary<long, object>();

    private void EditCheck(long checkid)
    {
        var key = dictionary.GetOrAdd(checkid, new object());
        lock (key)
        {
            //Do stuff with key
        }
    }
}

14
2017-09-25 15:26



tốt đẹp. một cải tiến hơn câu trả lời này - jltrem
Cảm ơn bạn cho câu trả lời của bạn tôi sẽ đọc lên trên ConcurrentDictionary và kiểm tra này. Nhưng có vẻ như chỉ là những gì tôi cần. - Dendei
Bạn cũng có thể muốn xem xét việc sử dụng ReadWriterLock nếu bạn sắp có nhiều chủ đề chỉ thực hiện các thao tác chỉ đọc trên checkid đồng thời, điều này sẽ cho phép nhiều chủ đề thực hiện tất cả các hoạt động đọc trên cùng một checkidnhưng một khi ai đó muốn viết nó sẽ khóa tất cả các độc giả đồng thời. - Scott Chamberlain
Xin lỗi nếu im chậm chấp nhận anwers tôi havent đã có thể kiểm tra này đúng nhưng bacuase chúng tôi sẽ kiểm tra ngày hôm nay nếu máy tính khách hàng của chúng tôi có thể có .net 4.0. vì chúng dựa trên xp nhưng không được liệt kê trong Hệ điều hành được hỗ trợ xD - Dendei
Tôi biết nó phụ thuộc vào yêu cầu chính xác và cách lớp này sẽ được sử dụng, nhưng bạn sẽ rất có thể muốn tuyên bố rằng ConcurrentDictionary như tĩnh, phải không? - Todd Menier


Khi bạn muốn cải thiện hiệu suất, bạn nên thực hiện khóa tại thời điểm gần đây nhất có thể. Khi bạn sử dụng cơ sở dữ liệu, bạn có thể sử dụng khóa DB. Bạn có hai lựa chọn:

  1. Sử dụng Select for update, nhìn vào Cách thích hợp để SQL chọn và cập nhật
  2. Sử dụng khóa lạc quan là cách tiếp cận tốt nhất của IMHO để làm điều đó, http://en.wikipedia.org/wiki/Optimistic_concurrency_control hoặc là http://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html

Lưu ý rằng cả hai cách tiếp cận cho phép bạn sử dụng tài nguyên DB nhiều hơn các phương thức có lập trình. Điều này tốt hơn là từ điển được đề xuất, tại sao?

Một khi bạn sẽ sao chép dữ liệu, những người trong DB được nhân đôi trong từ điển thời gian chạy, bạn buộc phải đồng bộ hóa chúng, vì vậy nếu ai đó cập nhật cơ sở dữ liệu và thêm mới id bạn cần cập nhật ngay từ điển.

Chắc chắn, nó có thể thực hiện cho việc duy trì nhỏ (ví dụ: kho lưu trữ) nhưng một khi dự án của bạn phát triển, một số đồng nghiệp của bạn có thể quên thông tin này và bạn sẽ bắt đầu tìm thấy loại lỗi đó.


0
2017-09-26 06:29