2009-10-30 52 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>()...