2016-10-05 3 views
2

У меня проблемы с удалением всех элементов из коллекции в рамках сущности, используя Clear()Как очистить() все элементы из ICollection от Entity Framework?

Рассмотрим часто используемый пример с блогами и сообщениями.

public class Blog 
{ 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public virtual ICollection<Post> Posts { get; set; } 
} 

public class Post 
{ 
    public int Id { get; set; } 

    // foreign key to Blog: 
    public int BlogId { get; set; } 
    public virtual Blog Blog { get; set; } 

    public string Title { get; set; } 
    public string Text { get; set; } 
} 

public class BlogContext : DbContext 
{ 
    public DbSet<Blog> Blogs {get; set;} 
    public DbSet<Post> Posts {get; set;} 
} 

В блоге много сообщений. Блог имеет ICollection сообщений. Существует прямая связь «один-ко-многим» между блогами и сообщениями.

Предположим, что я хочу, чтобы удалить все сообщения из блога

Конечно, я мог бы сделать следующее:

Blog myBlog = ... 
var postsToRemove = dbContext.Posts.Where(post => post.BlogId == myBlog.Id); 
dbContext.RemoveRange(postsToRemove); 
dbContext.SaveChanges(); 

Однако следующий кажется проще:

Blog myBlog = ... 
myBlog.Posts.Clear(); 
dbContext.SaveChanges(); 

Однако это приводит к исключению InvalidOperation:

операция не выполнена: связь не может быть изменена, поскольку одно или несколько свойств внешнего ключа не имеют значения NULL. Когда происходит изменение отношения, соответствующее свойство внешнего ключа устанавливается равным нулевому значению. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, для свойства внешнего ключа должно быть назначено другое ненулевое значение, или не связанный с ним объект должен быть удален.

Каков наилучший способ очистки коллекции? Есть ли для этого свободный отчет API?

+0

Насколько я знаю, нет, к сожалению, нет другого пути, кроме использования * .Remove() * или * .RemoveRange() *. Разумеется, кроме запуска SQL напрямую через EF, но это не подходит, я думаю. – Robert

+0

Ваш случай описан здесь: http://stackoverflow.com/a/6181060/6804888. Кажется, что без изменения модели вы должны вручную удалить объекты после их удаления из коллекции. – kiziu

ответ

1

Clear работает над отношениями, а не при удалении объекта.

Существует два рабочих решения (я думаю, более читаемый), которые вы написали.

dbContext.Posts.RemoveRange(myBlog.Posts); 
// Now (also before SaveChanges) the myBlog.Posts is empty 
dbContext.SaveChanges(); 

EDIT
RemoveRange также удаляет сообщения из Blog.Posts коллекции

+0

Если вы действительно хотите очистить коллекцию и удалить все элементы (например, в вопросе, это решение является лучшим для чтения. Однако, если у вас есть только идентификатор блога, сообщения которого вы хотите создать исходный метод, сначала сохраняет первый блог –

0

Существует разница между двумя образцами кода.

Ваш первый пример кода dbContext.RemoveRange(postsToRemove) удаляет записи Post. Поэтому любые отношения, связанные с этими записями, также удаляются.

В вашем втором примере кода myBlog.Posts.Clear() вы удаляете связь между myBlog и ее соответствующими Post отчетами. «Настоящее» базовое действие - установить значение BlogId из Post записей на null. К сожалению, это невозможно, так как BlogId установлено на не-nullable. Итак, короче говоря, связь удаляется, и никакие записи фактически не удаляются.

+0

Вы правы. Я понимаю, почему они выбирают этот метод.Есть примеры, когда удаление элементов при очистке коллекции нежелательно. –

Смежные вопросы