2009-10-30 48 views
3

跟進至this question。我有以下代碼:Linq to SQL:查詢不查看未完成的更改

string[] names = new[] { "Bob", "bob", "BoB" }; 
using (MyDataContext dataContext = new MyDataContext()) 
{ 
    foreach (var name in names) 
    { 
     string s = name; 
     if (dataContext.Users.SingleOrDefault(u => u.Name.ToUpper() == s.ToUpper()) == null) 
      dataContext.Users.InsertOnSubmit(new User { Name = name }); 
    } 

    dataContext.SubmitChanges(); 
} 

...並插入所有三個名稱(「Bob」,「bob」和「BoB」)。如果這是Linq-to-Objects,它不會。

我可以讓它看看待處理的更改以及表中已有的內容嗎?

回答

2

我不認爲這是可能的一般。想象一下,你犯了一個這樣的查詢:

dataContext.Users.InsertOnSubmit(new User { GroupId = 1 }); 
var groups = dataContext.Groups.Where(grp => grp.Users.Any()); 

數據庫一無所知新用戶(還),因爲插入尚未COMMITED,所以生成的SQL查詢可能無法與ID = 1返回集團。 DataContext在這種情況下可以考慮尚未提交的插入的唯一方法是獲取整個組表(如果它們受到查詢影響,可能還有更多表),並在客戶端上執行查詢,這當然是不可取的。我想L2S設計師認爲,如果一些查詢考慮到尚未提交的插入而另一些則不考慮,這將違反直覺,所以他們選擇不考慮它們。

你爲什麼不使用類似

foreach (var name in names.Distinct(StringComparer.InvariantCultureIgnoreCase)) 

進入數據庫之前過濾掉重複的名字?

+0

我不能使用names.Distinct,因爲名稱(在我的真實代碼中)也是來自另一個數據庫的Linq-to-SQL查詢。但是我關於L2S在一般情況下無法做到這一點的事實表明您的觀點。 – 2009-10-30 14:49:20

+0

@Roger:如果你想枚舉所有的名字,你必須從數據庫中獲取整個集合,所以爲什麼不使用.ToList()來獲取它們並在生成的Linq-To-Objects列表上使用.Distinct ? – Niki 2009-10-30 15:05:58

1

你爲什麼不嘗試這樣

foreach (var name in names) 
{ 
    string s = name; 
    if (dataContext.Users.SingleOrDefault(u => u.Name.ToUpper() == s.ToUpper()) == null) 
    { 
     dataContext.Users.InsertOnSubmit(new User { Name = name }); 
     break; 
    } 
} 
+0

因爲'名稱'可能還包含「Alice」和「Chuck」。爲了簡潔,我只是將它們排除在外。 – 2009-10-30 14:50:04

0

我很抱歉,我不明白的LINQ to SQL一樣多。

但是,當我看代碼時,它似乎告訴它使用SubmitChanges一次插入所有記錄(類似於事務),並且您試圖從數據庫中檢查它的存在,記錄是而不是插入。

編輯:嘗試將SubmitChanges放入循環中,看看代碼將按照您的期望運行。

+0

將SubmitChanges放入循環內會導致數據庫的額外往返。這是不可取的。 – 2009-10-30 14:50:35

0

您可以查詢相應ChangeSet集合,如

if(
    dataContext.Users. 
     Union(dataContext.GetChangeSet().Inserts). 
     Except(dataContext.GetChangeSet().Deletes). 
     SingleOrDefault(u => u.Name.ToUpper() == s.ToUpper()) == null) 

這將創建在用戶表和未決插入值的聯合,將排除掛起刪除。

當然,您可能需要創建一個changeSet變量以防止多次調用GetChangeSet函數,並且您可能需要適當地將集合中的對象轉換爲適當的類型。在「插入和刪除」集合中,您可能想要使用類似的方式對其進行過濾

...GetChangeSet().Inserts.Where(o => o.GetType() == typeof(User)).OfType<User>()...