2010-07-06 40 views
6

SQL Server 2008 Ent ASP.NET MVC 2.0 LINQ-to-SQLĐừng MERGE sử dụng LINQ to SQL

Tôi đang xây dựng một trang web chơi game, theo dõi khi một cầu thủ đặc biệt (toon) đã bắn rơi một con quái vật đặc biệt (trùm). Bảng trông giống như sau:

int ToonId 
int BossId 
datetime LastKillTime 

Tôi sử dụng dịch vụ bên thứ ba cung cấp cho tôi thông tin mới nhất (toon, boss, time).
Bây giờ tôi muốn cập nhật cơ sở dữ liệu của mình với thông tin mới đó.
Phương pháp tiếp cận vũ lực là thực hiện upsert theo từng dòng. Nhưng nó trông xấu xí (mã khôn ngoan), và có lẽ cũng chậm.

Tôi nghĩ giải pháp tốt hơn là chèn dữ liệu mới (sử dụng bảng tạm thời?) Và sau đó chạy câu lệnh MERGE.

Ý tưởng hay không? Tôi biết bảng tạm thời là "tốt hơn để tránh". Tôi có nên tạo bảng tạm thời "tạm thời" chỉ cho hoạt động này không?
Hoặc tôi chỉ nên đọc toàn bộ tập hợp hiện tại (tối đa 100 hàng), hợp nhất và đặt lại từ trong ứng dụng?

Mọi gợi ý/đề xuất luôn được đánh giá cao.

Trả lời

6

ORM là công cụ sai để thực hiện các thao tác theo lô và LINQ-to-SQL cũng không ngoại lệ. Trong trường hợp này tôi nghĩ rằng bạn đã chọn giải pháp đúng: Lưu trữ tất cả các mục trong bảng tạm thời một cách nhanh chóng, sau đó thực hiện UPSERT bằng cách hợp nhất.

Cách nhanh nhất để lưu trữ dữ liệu vào bảng tạm thời là sử dụng SqlBulkCopy để lưu trữ tất cả dữ liệu vào bảng bạn chọn.

-1

Trông giống như miếng chèn thẳng về phía trước.

private ToonModel _db = new ToonModel(); 
Toon t = new Toon(); 
t.ToonId = 1; 
t.BossId = 2; 
t.LastKillTime = DateTime.Now(); 
_db.Toons.InsertOnSubmit(t); 
_db.SubmitChanges(); 
+2

Nó sẽ không cho tôi "id trùng lặp" nếu tôi đã có Toon với Id = 1 chưa? –

6

Nếu bạn đang sử dụng LINQ-to-SQL, upserts không phải là xấu xí ..

foreach (var line in linesFromService) { 
    var kill = db.Kills.FirstOrDefault(t=>t.ToonId==line.ToonId && t.BossId==line.BossId); 
    if (kill == null) { 
     kill = new Kills() { ToonId = line.ToonId, BossId = line.BossId }; 
     db.Kills.InsertOnSubmit(kill); 
    } 
    kill.LastKillTime = line.LastKillTime; 
} 
db.SubmitChanges(); 

Không phải là một tác phẩm nghệ thuật, nhưng đẹp hơn trong SQL. Ngoài ra, chỉ với 100 hàng, tôi sẽ không quá lo ngại về hiệu suất.

+0

Tôi đồng ý, hiệu suất không phải là một mối quan tâm ở đây vì vậy hãy sử dụng phương pháp LINQ trên SQL xấu xí –

0

Để cập nhật mà không truy vấn các bản ghi trước, bạn có thể thực hiện các thao tác sau. Nó vẫn sẽ nhấn db một lần để kiểm tra xem kỷ lục tồn tại nhưng sẽ không kéo kỷ lục:

var blob = new Blob { Id = "some id", Value = "some value" }; // Id is primary key (PK) 

if (dbContext.Blobs.Contains(blob)) // if blob exists by PK then update 
{ 
    // This will update all columns that are not set in 'original' object. For 
    // this to work, Blob has to have UpdateCheck=Never for all properties except 
    // for primary keys. This will update the record without querying it first. 
    dbContext.Blobs.Attach(blob, original: new Blob { Id = blob.Id }); 
} 
else // insert 
{ 
    dbContext.Blobs.InsertOnSubmit(blob); 
} 
dbContext.Blobs.SubmitChanges(); 

Xem here cho một phương pháp mở rộng cho việc này.