简体   繁体   English

Linq to SQL-删除,如果失败继续

[英]Linq to sql - delete and if fails continue

If I have a table like: 如果我有一个像这样的表:

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

And I want to delete a list of schools, from schoolA to schoolZ (using LINQ-to-SQL): 我想删除一个学校列表,从schoolA到schoolZ(使用LINQ-to-SQL):

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

SchoolA and SchoolB will fail because of the FK references above 由于上述FK参考, SchoolASchoolB将失败

How can I continue and delete all other schools, discarding the ones where the exception occurred? 我如何继续并删除所有其他学校,而丢弃发生异常的学校?

Only include schools that don't have any students: 只包括没有学生的学校:

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

By default, LINQ to SQL fails on the first error and rolls back the transaction. 默认情况下,LINQ to SQL在第一个错误时失败并回滚事务。 If you want it to keep working on anything it can, you can pass in the ConflictMode overload on SubmitChanges to allow it to keep going. 如果希望它继续处理任何可能的事情,则可以在SubmitChanges上传递ConflictMode重载以使其继续运行。 The following sample from "LINQ in Action" tries to issue all of the queued updates and then output the conflicts that were encountered by handling the ChangeConflictException. 来自“ 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();
}

Naturally, it is much better to be proactive and only try to delete the records that are valid as Mark Cidade demonstrated. 自然地,主动进取要好得多,并且仅尝试删除Mark Cidade演示的有效记录。

我同意Mark Cidade的观点,但是我可以建议使用联接范围将单个请求发送到数据库服务器的改进。

I agree with Mark's solution. 我同意马克的解决方案。 If you wan't to delete the school and its students, you can use: 如果您不想删除学校及其学生,则可以使用:

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

db.submitChanges();

That way you are fulfilling the FK constraint, so no errors are thrown. 这样,您就可以满足FK约束,因此不会引发任何错误。

Found out a simple way 找出一个简单的方法

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;

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM