Linq to sql - delete,如果失败继续



如果我有一个这样的表:

StudentId  | ... | SchoolId
___________|_____|__________ 
1          | ... | SchoolA
2          | ... | SchoolA
3          | ... | SchoolB
...

我想删除学校列表,从schoolA到schoolZ(使用LINQ-to-SQL):

foreach(School s in schools){
    db.Schools.DeleteOnSubmit(s);
    db.submitChanges();
}

SchoolASchoolB将失败,因为上面的FK引用

如何继续并删除所有其他学校,丢弃发生异常的学校?

只包括没有学生的学校:

var schoolsToDelete = schools.Where(x => !x.Students.Any());
db.Schools.DeleteAllOnSubmit(schoolsToDelete); 
db.submitChanges();

默认情况下,LINQ to SQL在第一个错误时失败并回滚事务。如果你想让它继续工作,你可以在SubmitChanges上传递ConflictMode重载,让它继续工作。下面的示例来自"LINQ in Action",尝试发出所有排队的更新,然后输出处理ChangeConflictException时遇到的冲突。

try
{
    context.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException)
{
    var exceptionDetail = 
        from conflict in context.ChangeConflicts
        from member in conflict.MemberConflicts
        select new
        {
            TableName = GetTableName(context, conflict.Object),
            MemberName = member.Member.Name,
            CurrentValue = member.CurrentValue.ToString(),
            DatabaseValue = member.DatabaseValue.ToString(),
            OriginalValue = member.OriginalValue.ToString()
        };
    exceptionDetail.Dump();
}

当然,最好是积极主动,只尝试删除有效的记录,正如Mark Cidade所演示的。

我同意Mark Cidade的观点,但是我可以建议改进使用连接作用域向数据库服务器发送单个请求。

我同意Mark的方案。如果您不想删除学校及其学生,您可以使用:

foreach (School s in schools)
{
    db.Students.DeleteAllOnSubmit(s.Students);
    db.Schools.DeleteOnSubmit(s);
}
db.submitChanges();

这样您就满足了FK约束,因此不会抛出错误。

找到了一个简单的方法

foreach(School s in schools){
    try{
        db.Schools.DeleteOnSubmit(s);
        db.submitChanges();
    }
    catch(SqlException exp){
        if(exp.Message.Contains("The DELETE statement conflicted with the REFERENCE constraint"))   //just checking if is FK reference
            db.Schools.InsertOnSubmit(s);   //=)
        else
            throw;
    }
}

最新更新