Я получаю исключение 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>





Глядя на ваш код, метод 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);
}
}
}
}