如果我有一个这样的表:
StudentId | ... | SchoolId
___________|_____|__________
1 | ... | SchoolA
2 | ... | SchoolA
3 | ... | SchoolB
...
我想删除学校列表,从schoolA到schoolZ(使用LINQ-to-SQL):
foreach(School s in schools){
db.Schools.DeleteOnSubmit(s);
db.submitChanges();
}
SchoolA
和SchoolB
将失败,因为上面的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;
}
}