Linq to sql - удалить и, если не получится, продолжить - PullRequest
2 голосов
/ 30 августа 2011

Если у меня есть таблица типа:

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

Как я могу продолжить и удалить все другие школы, исключая те, где произошло исключение?

Ответы [ 5 ]

6 голосов
/ 30 августа 2011

Включают только школы, в которых нет учеников:

var schoolsToDelete = schools.Where(x => !x.Students.Any());
db.Schools.DeleteAllOnSubmit(schoolsToDelete); 
db.submitChanges();
1 голос
/ 30 августа 2011

По умолчанию LINQ to SQL завершается неудачно при первой ошибке и откатывает транзакцию.Если вы хотите, чтобы он продолжал работать над чем угодно, вы можете передать перегрузку ConflictMode на SubmitChanges, чтобы позволить ему продолжать работу.В следующем примере из «LINQ в действии» пытается выполнить все обновления, поставленные в очередь, и затем вывести конфликты, возникшие при обработке 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();
}

Естественно, гораздо лучше быть активным и пытаться удалять только те записи, которые действительны, как показал Марк Сидаде.

0 голосов
/ 31 августа 2011

Я согласен с решением Марка. Если вы не хотите удалять школу и ее учеников, вы можете использовать:

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

db.submitChanges();

Таким образом, вы выполняете ограничение FK, поэтому никаких ошибок не возникает.

0 голосов
/ 31 августа 2011

Обнаружил простой способ

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;

    }
}
0 голосов
/ 30 августа 2011

Я согласен с Марком Сидаде, но могу предложить усовершенствовать использование области соединения для отправки одного запроса на сервер базы данных.

...