Linq to SQL:查询不会查看挂起的更改

时间:2009-10-30 12:11:39

标签: linq-to-sql

跟进this question。我有以下代码:

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,那就不会。

我可以查看待处理的更改以及表中已有的更改吗?

4 个答案:

答案 0 :(得分:2)

我认为这不可能。想象一下,你做了这样的查询:

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

数据库对新用户一无所知(因为插件尚未提交),因此生成的SQL查询可能不会返回Id = 1的组.DataContext可以考虑的唯一方法是 - 在这种情况下提交插入将是获取整个Groups-Table(如果它们受查询影响,可能还有更多表)并在客户端上执行查询,这当然是不可取的。我想L2S设计师认为,如果某些查询考虑到尚未提交的插入而其他人不这样做,则会违反直觉,因此他们选择不考虑它们。

为什么不使用

之类的东西
foreach (var name in names.Distinct(StringComparer.InvariantCultureIgnoreCase))

在点击数据库之前过滤掉重复的名称?

答案 1 :(得分: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;
    }
}

答案 2 :(得分:0)

对不起,我不太了解LINQ to SQL。

但是,当我查看代码时,似乎您告诉它使用SubmitChanges一次插入所有记录(类似于事务),并且您正试图从DB检查它是否存在,当记录完全时。

编辑:尝试将SubmitChanges放入循环中,看看代码是否按照您的预期运行。

答案 3 :(得分:0)

您可以查询相应的ChangeSet集合,例如

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

这将在Users表和待处理的插入中创建值的并集,并将排除挂起的删除。

当然,您可能希望创建一个changeSet变量以防止多次调用GetChangeSet函数,并且您可能需要将集合中的对象适当地转换为适当的类型。在“插入和删除”集合中,您可能希望使用类似

的内容对其进行过滤
...GetChangeSet().Inserts.Where(o => o.GetType() == typeof(User)).OfType<User>()...