Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
WPF

Как внедрить модель во viewModel?

26.12.2024, 11:19. Показов 27483. Ответов 295
Метки mvvm (Все метки)

Студворк — интернет-сервис помощи студентам
День добрый. Есть у меня метод в проекте, который вызывается из конструктора. Метод по типу "Получить все из бд и вывести на экран".

Смущает меня то, как именно я это делаю. Когда происходит загрузка, UI блокируется. Да и в целом все очень медленно и дальше будет только хуже с добавлением данных.

Теперь код.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class BirdsViewModel : ObservableObject
{
    // [B]Конструктор[/B]
    public BirdsViewModel(IBirdRepository birdRepository, Func<BirdEntity, BirdViewModel> birdView) // [B]Прошу обратить 
//внимание на делегат. Его, думаю, и нужно заменять.[/B]
 
    {
        Birds = [];
        _birdView = birdView;
        _birdRepository = birdRepository;
        LoadBirds();
    }
 
// [B]Проблемный метод[/B]
private async void LoadBirds()
{
    var birds = await _birdRepository.GetAllAsync(); // [B]Получение данных из БД[/B]
    switch (Name)
    {
        default:
            foreach (var bird in birds)
                Birds.Add(_birdView(bird)); // [B]С помощью делегата я во ViewModel передаю Entity, 
//с которой та и работает. Есть ли другие методы подобной реализации, чтобы у каждой ViewModel был свой Entity?[/B]
            break;
    }
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.12.2024, 11:19
Ответы с готовыми решениями:

Как из ViewModel UserControl'a изменить свойство в ViewModel главного окна?
Недавно начал попытки создавать приложение WPF с применением MVVM, и у меня возник вопрос, который не даёт мне продвигаться в разработке...

Как зарегистрировать ViewModel через Autofac, создав между ViewModel и нужным View DataContext связь?
Доброго времени суток. Есть желание при регистрации ViewModel'и сразу же &quot;подключиться&quot; к DataContext'у у нужной View, как например: ...

WPF получить доступ из одной viewmodel к другой viewmodel
Собственно есть у меня две viewmodel, mainviewmodel и settingsviewmodel, в mainviewmodel есть вот такая штука private Visibility...

295
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
25.04.2025, 12:48
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от 2033 Посмотреть сообщение
Не знал, что для разных классов разные свойства.
Удивлю.
Даже для разных экземпляров одного класса - это будут разные свойства.
Это из общего Шарпа.

Цитата Сообщение от 2033 Посмотреть сообщение
Я так полагаю нужен конвертер, потому как привязать IsEnabled к противоположенному значению HasErrors не выходит.
Да.
Простейший конвертер.

Цитата Сообщение от 2033 Посмотреть сообщение
какое-то разделение логики кнопок. Где-то команды решают, можно ли нажать кнопку, а где-то кнопка сама отключается.
Да, так и есть.
Это даже не WPF, а общий Шарп и ООП.
Команда выполнится или нет - решается в её CanExecute.
В нём прописана зависимость от экземпляра CreateSetViewModel, передаваемого в параметре.
Так как экземпляров CreateSetViewModel может быть множество и непонятно какой из них будет передан в команду, то невозможно прокинуть обратную зависимость SaveWordCommand.RaiseCanExecuteChanged от CreateSetViewModel.HasErrors.

Теперь смотри уже слой View.
Здесь у нас есть представление экземпляра CreateSetViewModel в котором есть кнопка.
Команда для кнопки подтягивается из другого источника.
Но есть необходимость на уровне представления создать зависимость Button.IsEnabled не только от команды, но и от CreateSetViewModel.HasErrors. Соответственно мы её и создаём в Представление.

Другой вариант реализации, мы внедряем в экземпляр CreateSetViewModel команду из MainVM.
Это можно сделать в навигаторе.
И тогда команда уже "будет знать" с каким экземпляром она работает и уже можно будет прокинуть зависимость SaveWordCommand.RaiseCanExecuteChanged от CreateSetViewModel.HasErrors.
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
25.04.2025, 15:54  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Удивлю.
Даже для разных экземпляров одного класса - это будут разные свойства.
Это из общего Шарпа.
Вроде бы база, но в данном случае не очевидно было.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Но есть необходимость на уровне представления создать зависимость Button.IsEnabled не только от команды, но и от CreateSetViewModel.HasErrors. Соответственно мы её и создаём в Представление.
Могу ли я в таком случае убрать CanExecute, раз уж кнопка отключается таким образом? Или лучше оставить?

В общем добавил метод в реп по проверки имени на уникальность. Столкнулся с некоторыми проблемами.
Прежде всего, так как реп дженерик, а у IdDto только Id параметр, я не мог сравнивать имена. Добавил это свойство в IdDto, ему все равно там место, так как Name есть у всех сущностей.
Но как будто этому методу не место там, выделяется своей простотой. Пока что обращаюсь к коллекции с локальным кэшем, но что если бд не загружается сразу в кэш? Брать и проверять среди всех слов имя на уникальность? Кажется единственным вариантом.

C#
1
2
3
4
public bool IsUnique(string name)
{
    return readOnlyObservableCollection!.Any(t => t.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
}
Ну и в CreateSetViewModel теперь закидываю реп и проверяю введенное значение.
C#
1
2
3
4
5
6
7
8
9
10
11
12
public string Word {  get => Get<string>()!; 
    set 
    {
        ClearErrors();
        if (string.IsNullOrEmpty(value) || _wordRepository.IsUnique(value))
        {
            AddError("");
        }
        
        Set(value); 
    }
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
25.04.2025, 21:04
Цитата Сообщение от 2033 Посмотреть сообщение
Могу ли я в таком случае убрать CanExecute, раз уж кнопка отключается таким образом? Или лучше оставить?
Это как бы разный функционал.
Ведь необязательно в представлении будет кнопка.
Может быть любой ICommandSource.
Я понимаю, что на первый взгляд это кажется "масло масляное". Но как более понятно объяснить - не приходит в голову.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
25.04.2025, 21:04
Добавлено через 1 час 1 минуту
2033, вот вариант с прокидыванием команды в CreateSetViewModel:
C#
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    public class CreateSetViewModel : ViewModelBase
    {
        private readonly RelayCommand<CreateSetViewModel> saveCommand;
 
        public RelayCommand SaveCommand => GetCommand(
            () =>
            {
                saveCommand.Execute(this);
            },
            () =>
            {
                return saveCommand.CanExecute(this);
            });
 
        protected override void OnPropertyChanged(string propertyName, object? oldValue, object? newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
            SaveCommand.RaiseCanExecuteChanged();
        }
 
        public CreateSetViewModel(RelayCommand<CreateSetViewModel> saveCommand)
        {
            Id = 0;
            Set = string.Empty;
            Word = string.Empty;
            Definition = string.Empty;
 
            this.saveCommand = saveCommand;
            saveCommand.CanExecuteChanged += delegate { SaveCommand.RaiseCanExecuteChanged(); };
        }
C#
24
25
26
27
28
        public MainViewModel(IDbModel model)
        {
            this.model = model;
 
            createSetVM = new((RelayCommand<CreateSetViewModel>)SaveWordCommand);
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
25.04.2025, 21:18
Цитата Сообщение от 2033 Посмотреть сообщение
а у IdDto только Id параметр, я не мог сравнивать имена. Добавил это свойство в IdDto, ему все равно там место, так как Name есть у всех сущностей.
Если есть у всех - норм.
Если не у всех, то можете сделать производный класс и уже от него дальше плясать.
Пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace Flashcards.Liblary.Repository
{
    /// <summary>Базовый класс с идентификатором</summary>
    public abstract class IdDto(int id)
    {
        /// <summary>Целочисленный идентификатор</summary>
        public int Id { get; set; } = id;
 
    }
 
    /// <summary>Базовый класс с идентификатором</summary>
    public abstract class IdNameDto(int id, string name) : IdDto (id)
    {
        /// <summary>Название</summary>
        public string Name { get; set; } = name;
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System.Collections.ObjectModel;
 
namespace Flashcards.Liblary.Repository
{
    /// <summary>Репозиторий <see cref="IdDto"/>.</summary>
    public interface IRepository<TId> where TId : IdDto
    {
        /// <summary>Добавление записи в Репозиторий.</summary>
        /// <param name="idDto">Экземпляр с данными для добавления. Идентификатор <paramref name="id"/> игнорируется.</param>
        /// <remarks>Если не удалось создать или добавить экземпляр, то выкдывается исключение.
        /// Игнорирование <see cref="TId.Id"/> зависит от диалекта БД.
        /// Возможно для этого добавление логики в Репозиторий.</remarks>
        /// <returns>Созданный согласно параметров экземляр <see cref="IdDto"/> и добавленный в репозиторий.
        /// Идентификатор, возвращаемего экземпляра, присваивается репозиторием.</returns>
        Task<TId> AddAsync(TId idDto);
 
        /// <summary>Удаление записи с указанным идентификатором.</summary>
        /// <param name="id">Идентификатор.</param>
        /// <remarks>Если не удалось удалить, то выкидывается исключение.</remarks>
        Task DeleteAsync(int id);
 
        /// <summary>Обновление записи Репозитория.</summary>
        /// <param name="idDto">Экземпляр с данными для обновления.
        /// Идентификатор остаётся неизменным, его поменять невозможно.</param>
        /// <remarks>Если не удалось обновить или создать экземпляр, то выкдывается исключение.</remarks>
        Task UpdateAsync(TId idDto);
 
        /// <summary>Возвращает отражение локального кеша БД.</summary>
        /// <returns>Метод возвращает всегда одby и тот же экземпляр <see cref="ReadOnlyObservableCollection{T}"/>.</returns>
        ReadOnlyObservableCollection<TId> GetObservableCollection();
 
        /// <summary>Асинхронная загрузка локального кеша (Eager loading).</summary>
        /// <returns>Задача в которой выполняется Асинхронная загрузка локального кеша.</returns>
        Task LoadAsync();
 
        /// <summary>Получение всех записей.</summary>
        /// <returns>Последовательность со всеми записями.</returns>
        /// <remarks>В методе производится новый запрос к БД, в отличии от метода <see cref="GetObservableCollection"/>,
        /// в котором возвращается отражение локального кеша без нового запроса в БД.</remarks>
        Task<IEnumerable<TId>> GetAllAsync();
    }
 
    /// <summary>Репозиторий <see cref="IdNameDto"/>.</summary>
    public interface INameRepository<TIdName> : IRepository<TIdName> where TIdName : IdNameDto
    {
        bool IsUnique(string name);
    }
}
C#
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace Flashcards.Liblary.Repository
{
    /// <summary>Дженерик Репозиторий для БД</summary>
    public class DbNameRepository<TId> : INameRepository<TId> where TId : IdNameDto
    {
        private readonly DbContext context;
        private readonly Func<DbContext> contextCreator;
        private readonly DbSet<TId> dbSet;
 
        /// <summary>Конструктор Репозитория.</summary>
        /// <param name="context">Постоянный Контекст БД, используемый для синхронизации через локальный кеш.</param>
        /// <param name="contextCreator">Функция, создающая новый одноразовый DbContext,
        /// из которого можно получить <see cref="DbSet{TEntity}">DbSet&lt;<typeparamref name="TId"/>&gt;</see>.</param>
        public DbNameRepository(DbContext context, Func<DbContext> contextCreator)
        {
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
28.04.2025, 05:49  [ТС]
Элд Хасп, ловлю дэдлок в методе по получению всех записей из бд. Не понимаю кто кого ждет из потоков.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
public async Task<bool> IsUnique(string name)
{
    if (await GetAllAsync() is IEnumerable<Word> words)
    {
        return words.Any(w => w.Name == name);
    }
    return false;
}
 
public async Task<IEnumerable<TId>> GetAllAsync() => await Task.Run(() =>
{
    return context.Set<TId>().ToList().Select(b => b);
});
Также не могу awaitить метод из свойства. Пока что вызываю Result, что можно придумать в таком случае?
C#
1
2
3
4
5
6
7
8
9
10
11
12
public string Word {  get => Get<string>()!; 
    set 
    {
        ClearErrors();
        if (_wordRepository.IsUnique(value).Result)
        {
            AddError("");
        }
        
        Set(value); 
    }
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
28.04.2025, 11:04
Цитата Сообщение от 2033 Посмотреть сообщение
дэдлок в методе по получению всех записей из бд.
Явного криминал в методе GetAllAsync() не вижу.
Не думаю что проблема в этих фрагментах кода.

Добавлено через 5 минут
Цитата Сообщение от 2033 Посмотреть сообщение
Task<bool> IsUnique(string name)
В этом методе нет причины для дедлока, но сам по себе он по локике "косячный".
Делается ПОЛНАЯ ВЫГРУЗКА из бд и потом в ней ищется имя.
Это ОООООчень не эффективно.
Пороверка уникальности должна производится средствами БД.
1) В БД устанавливается уникальная индексация для Word.Name;
2) Запрос делается так:
C#
1
2
3
4
public async Task<bool> IsUnique(string name) => await Task.Run(() =>
{
    return context.Set<TIdName>().Any(w => w.Name == name);
};
Добавлено через 8 минут
Цитата Сообщение от 2033 Посмотреть сообщение
Также не могу awaitить метод из свойства. Пока что вызываю Result, что можно придумать в таком случае?
Здесь только asynс void.

Примерная логика:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private async void ValidateWordAsync()
{
    string word = Word; // кешируется валидируемое значение
    AddError("Процесс валидации"); // Здесь обычно не стринг сообщение, а другой тип.
 
    try
    {
        var erorr = await Task(() =>model.ValidateWord(word));
        if(word != Word)
            return;
 
        // Обработка возращённой ошибки.
    }
    catch
    {
        // Обработка исключений
    }
}
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
28.04.2025, 16:57  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
1) В БД устанавливается уникальная индексация для Word.Name;
2) Запрос делается так:
Уникальная индексация обязательна? Она у меня сейчас установлена, но вдруг, например, я захочу в одной бд хранить одинаковые слова, просто для разных пользователей, к примеру.

Во втором пункте можно пожалуйста, если не сложно, по порядку. Что происходит?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Здесь только asynс void.
Примерная логика:
Вот тут совсем не понял. Async void для чего? Я спрашивал про свойство, свойству async не задать. Значит речь про метод.
Метод ValidateWord внутри метода ValidateWord - это метод из репа? Если не сложно, опишите пожалуйста процесс.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
28.04.2025, 18:27
Цитата Сообщение от 2033 Посмотреть сообщение
Уникальная индексация обязательна? Она у меня сейчас установлена, но вдруг, например, я захочу в одной бд хранить одинаковые слова, просто для разных пользователей, к примеру.
У вас требования к IRepository какие?
Если IsUnique - это уникальность именно имени, то естественно подразумевается, что в БД оно тоже будет уникальным.

Если же IsUnique - это какая-то разветвлённая логика по нескольким полям, то реализовываться метод должен уже не в абстрактном, а в конкретном репозитории:
C#
1
2
3
4
    public abstract class DbRepository<TId> : INameRepository<TId> where TId : IdDto
    {
 
          public abstract Task<bool> IsUnique(string name);
C#
1
2
3
4
    public abstract class WordDbRepository : INameRepository<Word> 
    {
 
          public override Task<bool> IsUnique(string name) => ....
Добавлено через 1 минуту
Во втором случае в БД может не быть индексации, но с очень высокой вероятностью, она может помочь.
Даже если нет индексации, выполнение запроса через БД, без полной выгрузке всё равно будет многократно быстрее.

Добавлено через 9 минут
Цитата Сообщение от 2033 Посмотреть сообщение
Вот тут совсем не понял. Async void для чего? Я спрашивал про свойство, свойству async не задать. Значит речь про метод.
Метод ValidateWord внутри метода ValidateWord - это метод из репа? Если не сложно, опишите пожалуйста процесс.
Из свойства можно вызвать async метод только без ожидания.
Поэтому обычно это бывают async void методы:
C#
1
2
3
4
5
6
7
public string Word {  get => Get<string>()!; 
    set 
    {
        Set(value); 
        ValidateWordAsync();
    }
}
Добавлено через 1 минуту
Обычно даже такие зависимости выносят в отдельный метод.
В данном случае в метод OnPropertyChanged.
Свойство содержит только логику по работе со своим полем.
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
29.04.2025, 04:24  [ТС]
Элд Хасп, я так полагаю тут должно быть Task.Run. А почему не просто await?

C#
1
var error = await Task(() =>model.ValidateWord(word));
Вот так.
C#
1
var error = await model.ValidateWord(word);
Получаю такое вот исключение на данный момент.


Весь измененный код.
Кликните здесь для просмотра всего текста

Из этого класса при попытке загрузить бд в контекст
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class DbModel : IDbModel
{
    private readonly DbContext context;
 
    public IRepository<Word> Words { get; }
    public IRepository<Set> Sets { get; }
 
    public Task LoadAsync() => Task.Run(() =>
    {
        context.Set<Word>().Load(); // В этом месте исключение
        context.Set<Set>().Load();
    });
 
    /// <summary>Конструктор Репозитория.</summary>
    /// <param name="context">Постоянный Контекст БД используемый для синхронизации через локальный кеш.</param>
    /// <param name="contextCreator">Функция создающая новый одноразовый DbContext из которого можно получить
    /// <see cref="DbSet{TEntity}">DbSet&lt;<typeparamref name="TId"/>&gt;</see>.</param>
    public DbModel(DbContext context, Func<DbContext> contextCreator)
    {
        //context.Database.EnsureCreated();
        this.context = context;
 
        Words = new DbRepository<Word>(context, contextCreator);
        Sets = new DbRepository<Set>(context, contextCreator);
    }
}
C#
1
2
3
4
5
6
7
public string Word {  get => Get<string>()!; 
    set 
    {
        Set(value);
        ValidateWordAsync();
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private async void ValidateWordAsync()
{
    string word = Word; // кэшируется валидируемое значение
    AddError("Процесс валидации"); // Здесь обычно не стринг сообщение, а другой тип.
 
    try
    {
        var error = await _wordRepository.IsUnique(word);
        if (word != Word)
            return;
 
        // Обработка возращённой ошибки.
    }
    catch
    {
        // Обработка исключений
    }
}
Метод из бд. Тоже не первый раз уже вижу, синтаксис привычный, но до сих пор не понимаю, что тут пошагово происходит. Каким образом здесь происходит проверка на стороне бд.
C#
1
2
3
4
public async Task<bool> IsUnique(string name) => await Task.Run(() =>
{
    return context.Set<TId>().Any(w => w.Name == name);
});
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
29.04.2025, 11:48
Цитата Сообщение от 2033 Посмотреть сообщение
А почему не просто await?
Если метод model.ValidateWord(word) синхронный, то нужно вызывать его в задаче, чтобы выполнение было асинхронным.

Цитата Сообщение от 2033 Посмотреть сообщение
Получаю такое вот исключение на данный момент.
Не всякий DbContext позволяет одновременно две операции. Это зависит от БД и библы создающей DbContext для этой БД.
Если используется один DbContext для всех операций, то надо его лочить перед обращением к нему.

Добавлено через 3 минуты
Цитата Сообщение от 2033 Посмотреть сообщение
Из этого класса при попытке загрузить бд в контекст
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DbModel : IDbModel
{
    private readonly DbContext context;
    private readonly object locker = new();
 
    public IRepository<Word> Words { get; }
    public IRepository<Set> Sets { get; }
 
    public Task LoadAsync() => Task.Run(() =>
    {
        lock(locker){
        context.Set<Word>().Load(); // В этом месте исключение
        context.Set<Set>().Load();}
    });
 
    /// <summary>Конструктор Репозитория.</summary>
    /// <param name="context">Постоянный Контекст БД используемый для синхронизации через локальный кеш.</param>
    /// <param name="contextCreator">Функция создающая новый одноразовый DbContext из которого можно получить
    /// <see cref="DbSet{TEntity}">DbSet&lt;<typeparamref name="TId"/>&gt;</see>.</param>
    public DbModel(DbContext context, Func<DbContext> contextCreator)
    {
        //context.Database.EnsureCreated();
        this.context = context;
 
        Words = new DbRepository<Word>(context, contextCreator);
        Sets = new DbRepository<Set>(context, contextCreator);
    }
}
C#
1
2
3
4
5
6
public async Task<bool> IsUnique(string name) => await Task.Run(() =>
{
    lock(locker){
        return context.Set<TId>().Any(w => w.Name == name);
    }
});
Добавлено через 1 минуту
2033, но когда два репа на одном DbContext придётся ещё и локер передавать кроме самого DbContext.

Добавлено через 29 секунд
Так же можно попробовать использовать асинхронные методы DbContext

Добавлено через 3 минуты
Асинхронный запрос и сохранение

Добавлено через 3 минуты
Вот здесь два ответа прочитайте: https://stackoverflow.com/a/20995146/13349759
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
30.04.2025, 04:14  [ТС]
Элд Хасп, появилось это все после добавления этой валидации. Наверное там что-то типа такого: инициализируется бд и сразу же при старте приложения идет попытка валидировать свойство Word, отсюда и два обращения к DbContext. Мне же в принципе нужно только узнать есть ли слово в бд, могу ли я через единоразовый контекст делать это?

Добавлено через 1 минуту
Элд Хасп, только теперь я почему-то проект запустить не могу, нажимаю запустить отладку, сразу же останавливает, чего уже только не попробовал. Другие проекты запускает, а тут даже в app не заходит.

https://disk.yandex.ru/i/VjOdZuKfaCuGsg

Предположительно могу грешить на замену процессора, вчера обновил.
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
30.04.2025, 04:56  [ТС]
Помогло добавление в свойства проекта строчки
C#
1
<CETCompat>false</CETCompat>
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
01.05.2025, 23:27
Цитата Сообщение от 2033 Посмотреть сообщение
только теперь я почему-то проект запустить не могу, нажимаю запустить отладку, сразу же останавливает, чего уже только не попробовал. Другие проекты запускает, а тут даже в app не заходит.
Попробуйте заменить синхронные обращения на асинхронные:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection;
 
namespace Flashcards.Liblary.Repository
{
    /// <summary>Дженерик Репозиторий для БД</summary>
    public class DbRepository<TId> : IRepository<TId> where TId : IdDto
    {
        private readonly DbContext context;
        private readonly Func<DbContext> contextCreator;
        private readonly DbSet<TId> dbSet;
 
        /// <summary>Конструктор Репозитория.</summary>
        /// <param name="context">Постоянный Контекст БД, используемый для синхронизации через локальный кеш.</param>
        /// <param name="contextCreator">Функция, создающая новый одноразовый DbContext,
        /// из которого можно получить <see cref="DbSet{TEntity}">DbSet&lt;<typeparamref name="TId"/>&gt;</see>.</param>
        public DbRepository(DbContext context, Func<DbContext> contextCreator)
        {
            context.Database.EnsureCreated();
            this.context = context;
            dbSet = context.Set<TId>();
            this.contextCreator = contextCreator;
        }
 
        public async Task<TId> AddAsync(TId idDto) => await Task.Run(async () =>
        {
            // Добавление сущности через другой, одноразовый Контекст БД.
            using (DbContext context = contextCreator())
            {
                DbSet<TId> set = context.Set<TId>();
                set.Add(idDto);
                context.SaveChanges();
            }
            // Получение сущности в локальный кеш и её возврат.
            return await dbSet.FindAsync(idDto.Id) ?? throw new Exception("Не добавилась.");
        });
 
        public async Task DeleteAsync(int id) => await Task.Run(async () =>
        {
            // Удаление сущности через другой, одноразовый Контекст БД.
            using (DbContext context = contextCreator())
            {
                DbSet<TId> set = context.Set<TId>();
                TId ent = set.Find(id) ?? throw new Exception("Записи с таким Id нет.");
                set.Remove(ent);
                context.SaveChanges();
            }
            {
                // Обновление локального кеша, если там есть сущность с таким Id.
                TId? ent = await dbSet.FindAsync(id);
                if (ent is not null)
                {
                   await dbSet.Entry(ent).ReloadAsync();
                }
            }
        });
 
        public async Task<IEnumerable<TId>> GetAllAsync() => await Task.Run(() =>
        {
            return context.Set<TId>().ToList().Select(b => b);
        });
 
        private ReadOnlyObservableCollection<TId>? readOnlyObservableCollection;
 
        public ReadOnlyObservableCollection<TId> GetObservableCollection()
        {
            readOnlyObservableCollection ??= new(dbSet.Local.ToObservableCollection());
            return readOnlyObservableCollection;
        }
 
        public async Task UpdateAsync(TId idDto) => await Task.Run(async () =>
        {
            // Обновление записи в БД через другой, одноразовый Контекст БД.
            using (DbContext context = contextCreator()) // Создание одноразового Контекста БД.
            {
                DbSet<TId> set = context.Set<TId>();
 
                _ = set.Update(idDto);
                _ = context.SaveChanges();
            }
 
            // Обновление сущности с уведомлением привязок через PropertyDescriptor об изменении Bird.IsActive.
            // Вариант показан, как альтернативная реализация.
            // В данной задаче, на практике, более лучшим вариантом будет замена сущности.
            EntityEntry<TId>? ent = dbSet.Local.FindEntry(idDto.Id);
            await ent!.ReloadAsync();
            TId tid = await dbSet.FindAsync(idDto.Id) ?? throw new NullReferenceException();
 
            OnAllPropertiesChanged(tid);
        });
 
        public async Task<bool> IsUnique(string name) => await Task.Run(() =>
        {
            using var context = contextCreator();
            return context.Set<TId>().Any(w => w.Name == name);
        });
 
        private static readonly PropertyChangedEventArgs args = new(string.Empty);
 
        // Создание метода для уведомления об обновлении всех свойств Bird
        private static readonly ImmutableArray<Action<object, EventArgs>> allPropertiesChangedHandler;
 
        static DbRepository()
        {
            var onValueChanged = typeof(PropertyDescriptor)
                .GetMethod($"OnValueChanged", BindingFlags.Instance | BindingFlags.NonPublic)!;
            allPropertiesChangedHandler = TypeDescriptor.GetProperties(typeof(TId))
                .Cast<PropertyDescriptor>()
                .Select(onValueChanged.CreateDelegate<Action<object, EventArgs>>)
                .ToImmutableArray();
        }
 
        // Метод обновляющий все привязки к Bird.
        private static void OnAllPropertiesChanged(TId ent)
        {
            foreach (var p in allPropertiesChangedHandler)
            {
                p(ent, args);
            }
        }
 
        public async Task LoadAsync() => await Task.Run(async () => await dbSet.LoadAsync());
    }
}
0
 Аватар для 2033
4 / 4 / 1
Регистрация: 26.12.2024
Сообщений: 225
07.05.2025, 17:03  [ТС]
Элд Хасп, день добрый. Правильно ли я понимаю, что в saferep проекте, когда идет привязка к наблюдаемой коллекции, та содержит в себе по сути ссылку на другую коллекцию?

На 25 строке коллекция инициализируется и больше никак сама не обновляется. К свойству на 67 строке уже идет привязка к этой коллекции во View.

Добавлено через 54 секунды
Имею ввиду нет никакого добавления в коллекцию эту в событии.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
07.05.2025, 21:15
Цитата Сообщение от 2033 Посмотреть сообщение
Имею ввиду нет никакого добавления в коллекцию эту в событии.
Подключение обработчика к событию.

C#
27
            birdsRepository.RepChanged += OnbirdsRepositoryChanged;
Ну, и в самом обработчике обновление коллекции privateBirds: инициализация, добавление, удаление и прочее.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.05.2025, 21:15

Mvvm ViewModel в ViewModel
Есть одно окошко там много вкладок, в каждой вкладке есть подвкладки и там много разных таблиц и кнопок. ViewModel будет просто огромной,...

Как внедрить БД в exe на VB 6.0
Hi! Есть база на Access 7.0 и проект на VB 6.0. Можно ли как-нибудь всунуть .mdb файл в exe-шник, чтобы никто не мог его открыть и...

Как внедрить функцию
Здравствуйте, есть программа которая считает в edit сколько открывающихся скобок и закрывающихся. мой код выглядит так: procedure...

как с внедрить свой код
Всем привет! Не подскажите как можно создать свою папку в вордпресссом и внедрить свой код. Сейчас есть сайт на вордпресс, там нужно...

Как внедрить ProgressBar в макрос
Добрый день! почитал соседние темки на эту тему, нашел у товарища analyst архив с замечательными формами ProgressBar но так как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
296
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru