Исключение объекта, удаленное при добавлении/удалении из наблюдаемой коллекции

Я получаю исключение ObjectDispose при добавлении и удалении элементов из наблюдаемой коллекции.

Добавление

Если я добавляю в коллекцию один новый элемент, он работает нормально, но если я попытаюсь добавить второй при том же запуске программы, я получу исключение Object Dispose. Если я закрою и перезапущу программу, я смогу добавить еще 1, но не более того.

Удаление

Если я удалю элемент, который был добавлен в базу данных с момента последнего запуска программы, он будет работать нормально и удалит его. Однако, если я добавляю что-то в тот же запуск, а затем пытаюсь удалить то, что я только что добавил, это вызывает исключение.

Сообщение об ошибке:

System.ObjectDisposeException: 'Невозможно получить доступ к удаленному экземпляру контекста. Распространенной причиной этой ошибки является удаление экземпляра контекста, который был разрешен в результате внедрения зависимостей, а затем попытка использовать тот же экземпляр контекста в другом месте вашего приложения. Это может произойти, если вы вызываете Dispose для экземпляра контекста или заключаете его в оператор using. Если вы используете внедрение зависимостей, вы должны позволить контейнеру внедрения зависимостей позаботиться об удалении экземпляров контекста. Имя объекта: «RecipeDBContext».

Я использую Entity Framework Core с базой данных SqlLite, WinUi 3 и набором инструментов сообщества MVVM.

Посмотреть модель

public partial class UserViewModel : ObservableObject
{
    RecipeDBContext context;

    [ObservableProperty]
    private ObservableCollection<User> _users;      

    public UserViewModel()
    {
        context = new RecipeDBContext();
        _users = new ObservableCollection<User>();
        UpdateUsers(context.User.ToList());
        _users.CollectionChanged += this.OnCollectionChanged;        
    }

    public void UpdateUsers(List<User> users)
    {
        _users.Clear();
        foreach (User user in users)
        {            
            Users.Add(user);
        }
    }

    void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {        
        if (e.NewItems != null)
        {
            foreach (User newItem in e.NewItems)
            {                                               
                context.User.Add(newItem);                
            }            
        }

        if (e.OldItems != null)
        {
            foreach (User oldItem in e.OldItems)
            {                
                context.User.Remove(oldItem);                
            }            
        }
        context.SaveChanges();
    }

   [RelayCommand]
   private void DeleteUser(User user)
   {
      Users.Remove(user);
   }
   
   [RelayCommand]
   public void AddUser(object o)
   {
      if (o != null)
      {
          string username = o as string;
         if (username != String.Empty)
         {
            using (context)
            {
                var user = new User()
                {                            
                    Username = username,
                };
                Users.Add(user);                                                
            }
        }
    }
}

Модель

public partial class User: ObservableObject
{
    public int Id { get; set; }

    [ObservableProperty]
    private string _username = string.Empty;

    
    partial void OnUsernameChanged(string? oldValue, string newValue)
    {
        
    }
}

ДбКонтекст

public class RecipeDBContext: DbContext
{    
    public DbSet<User> User { get; set; }

    public RecipeDBContext() 
    {
        Database.EnsureCreated();
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=recipe.db");
    }
}

Вид

<Page
    x:Class = "Test.Views.UserPage"
    xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local = "using:Test.Views"
    xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm = "using:Test.ViewModels"    
    mc:Ignorable = "d"    
    xmlns:m = "using:Test.Models"
    x:Name = "ThisPage">

    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height = "0.2*"></RowDefinition>
            <RowDefinition Height = "Auto"></RowDefinition>
            <RowDefinition Height = "Auto"></RowDefinition>
            <RowDefinition Height = "Auto"></RowDefinition>
            <RowDefinition Height = "Auto"></RowDefinition>
            <RowDefinition Height = "Auto"></RowDefinition>
            <RowDefinition Height = "Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width = "0.3*"></ColumnDefinition>
            <ColumnDefinition Width = "0.3*"></ColumnDefinition>
            <ColumnDefinition Width = "0.3*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Border BorderThickness = "1" BorderBrush = "Black" />
        <TextBlock FontSize = "30" Grid.Row = "0" Grid.Column = "0">LOGIN</TextBlock>
        <TextBlock Grid.Row = "1" Grid.Column = "0">User</TextBlock>
        <ListView x:Name = "usersListView" Grid.Row = "1" Grid.Column = "1" ItemsSource = "{x:Bind ViewModel.Users, Mode=TwoWay}">
            <ListView.Header>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width = "0.3*"></ColumnDefinition>
                        <ColumnDefinition Width = "0.3*"></ColumnDefinition>
                        <ColumnDefinition Width = "0.3*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <ListViewHeaderItem  Grid.Column = "0">
                        <TextBlock>Username</TextBlock>
                    </ListViewHeaderItem>
                    <ListViewHeaderItem  Grid.Column = "1">
                        <TextBlock>Recipes</TextBlock>
                    </ListViewHeaderItem>
                    <ListViewHeaderItem  Grid.Column = "2">
                        <TextBlock>Delete</TextBlock>
                    </ListViewHeaderItem>
                </Grid>
            </ListView.Header>

            <ListView.ItemTemplate>
                <DataTemplate x:DataType = "m:User">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width = "0.3*"></ColumnDefinition>
                            <ColumnDefinition Width = "0.3*"></ColumnDefinition>
                            <ColumnDefinition Width = "0.3*"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text = "{x:Bind Username}" Grid.Column = "0"></TextBlock>
                        <Button Grid.Column = "2" 
                                Command = "{Binding ElementName=ThisPage, Path=ViewModel.DeleteUserCommand}"
                                CommandParameter = "{x:Bind}" 
                                Content = "X"/>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <TextBlock Grid.Row = "3" Grid.Column = "0" FontSize = "30">New User</TextBlock>
        <TextBlock Grid.Row = "4" Grid.Column = "0">Name</TextBlock>
        <TextBox x:Name = "newUserName" Grid.Row = "4" Grid.Column = "1"></TextBox>
        <Button x:Name = "addUserBtn1" Command = "{x:Bind ViewModel.AddUserCommand}" CommandParameter = "{Binding Text, ElementName=newUserName}" Grid.Row = "5" Grid.Column = "2">Add User</Button>
    </Grid>
</Page>
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Глядя на ваш код, метод AddUser имеет using(context), который вызывает context.Dispose() в конце блока - и вы получаете System.ObjectDisposedException. Просто пока опустите using.

[RelayCommand]
public void AddUser(object o) {
    if (o != null) {
        string username = o as string;
        if (username != String.Empty) {
            using (context) { // you are disposing
                var user = new User() {
                    Username = username,
                };
                Users.Add(user);
            }
        }
    }
}

Другие вопросы по теме