2012-07-02 99 views
1

我嘗試將SQL刪除命令更改爲LINQ。這是我的SQL命令:使用LINQ刪除記錄時出錯

DELETE FROM [TrackPoints] 
WHERE [RouteFK] IN (SELECT RouteId 
        FROM Routes 
        WHERE UserId = @UserId) 

,這是LINQ的代碼,我已經寫了:

int UID =1; 
FirstDataContext aspnetdb = new FirstDataContext(); 
var res1 = from q1 in aspnetdb.Routes 
      where q1.UserId == UID 
      select q1.RouteId; 
foreach (var k in res1) 
{ 
    var eigen = from p in aspnetdb.Trackpoints 
       where p.RouteFK == k 
       select p.TrackPointId; 

    aspnetdb.Trackpoints.DeleteOnSubmit(eigen.First()); 
    aspnetdb.SubmitChanges(); 
} 

但在此行中我有一個錯誤:

aspnetdb.Trackpoints.DeleteOnSubmit(eigen.First()); 

提到:

The best overloaded method match for 'System.Data.Linq.Table.DeleteOnSubmit(LINQ_Test.Trackpoint)' has some invalid arguments

我該怎麼辦?

+0

的LINQ to SQL或實體框架? – abatishchev

+0

LINQ to SQL。你能否簡要解釋一下LINQ to SQL和Entity Framework之間的區別? – Kabi

+0

LINQ to SQL是Microsoft在實體框架之前的一個ORM,現在已被廢棄和廢棄。 – abatishchev

回答

5

使用此:

var eigen = (from p in aspnetdb.Trackpoints 
      where p.RouteFK == k 
      select p).First(); 

或什麼是更短:

var eigen = aspnetdb.Trackpoints.First(p => p.RouteFK == k); 

,因爲它返回Trackpoint

當你select p.TrackPointId回報Int


var r = from r in aspnetdb.Routes 
     join p in aspnetdb.Trackpoints on p.RouteId equals r.RouteFK 
     where r.UserId == UID 
     select p; 

foreach (var x in r) 
{ 
    aspnetdb.Trackpoints.DeleteOnSubmit(x); 
} 
aspnetdb.SubmitChanges(); 
+0

您已優化我的代碼,非常好,謝謝:) – Kabi

+2

@Kabi:還請注意調用'DeleteAllOnSubmit'以進一步簡化代碼的選項... –

2

的問題是,你只是選擇ID,然後沒有方法簽名匹配。我想你的代碼實際上更改爲:

var entity = aspnetdb.Trackpoints.Where(p => p.RouteFK == k).Single(); 
aspnetdb.Trackpoints.DeleteOnSubmit(entity); 

(由您改變select條款時只select p變得毫無意義使用查詢表達式 - 並且一旦你使用的方法調用的語法,這是有道理的調用SingleFirst在同一個語句。按照abatishchev的回答,這也可能是aspnetdb.Trackpoints.Single(p => p.RouteFK == k)。)

這是假設你已經肯定了1(僅1)實體對給定RouteFK,由方式。

實際上,選擇全部您希望在單個查詢中刪除的實體可能會更好。例如:

var entitiesToDelete = from q1 in aspnetdb.Routes 
         where q1.UserId == UID 
         join p in aspnetdb.TrackPoints 
         on q1.RouteID equals p.RouteFK 
         select p; 

aspnetdb.Trackpoints.DeleteAllOnSubmit(entitiesToDelete); 
aspnetdb.SubmitChanges(); 

或者,如果你有你的聯接設置你的模型正確,你也許可以擺脫明確的加入:

var entitiesToDelete = from q1 in aspnetdb.Routes 
         where q1.UserId == UID 
         select q1.Route; // Or Track, or whatever it is 

aspnetdb.Trackpoints.DeleteAllOnSubmit(entitiesToDelete); 
aspnetdb.SubmitChanges(); 

在這兩種情況下,你能避免做幾乎同樣多的查詢。 (您避免了「n + 1選擇」問題。)

1

DeleteOnSubmit方法需要域對象。您的代碼改爲通過ID。此外,您沒有條件檢查項目是否確實存在。

嘗試你的日常改寫爲這樣的:

 foreach (var k in res1) 
     { 
      var eigen = from p in aspnetdb.Trackpoints 
         where p.RouteFK == k 
         select p; 

      var item = eigen.FirstOrDefault(); 

      if (item != null) 
      { 
       aspnetdb.Trackpoints.DeleteOnSubmit(item); 
       aspnetdb.SubmitChanges(); 
      } 

     }