Для начала я бы порекомендовал вам , а не , чтобы использовать события здесь.События - это то, что может показаться очень полезным, но из-за того, как они работают (синхронно), они на самом деле не лучший способ достичь этого в веб-контексте, особенно в асинхронной среде, такой как ASP.NET Core.
Вместо этого я бы порекомендовал вам просто объявить свой собственный тип, например IAppointmentChangeHandler
, например:
public interface IAppointmentChangeHandler
{
Task AddAppointment(ScheduleData appointment);
Task UpdateAppointment(ScheduleData appointment);
Task RemoveAppointment(ScheduleData appointment);
}
Ваш NotificationService
может просто реализовать такой интерфейс, чтобы иметь возможностьдля обработки этих событий (очевидно, просто отправьте туда все, что вам нужно):
public class NotificationService : IAppointmentChangeHandler
{
private readonly IHubContext _hubContext;
public NotificationService(IHubContext hubContext)
{
_hubContext = hubContext;
}
public AddAppointment(ScheduleData appointment)
{
await _hubContext.Clients.InvokeAsync("AddAppointment", appointment);
}
public UpdateAppointment(ScheduleData appointment)
{
await _hubContext.Clients.InvokeAsync("UpdateAppointment", appointment);
}
public RemoveAppointment(ScheduleData appointment)
{
await _hubContext.Clients.InvokeAsync("RemoveAppointment", appointment);
}
}
А внутри вашего контроллера вы просто вводите этот IAppointmentChangeHandler
и вызываете реальный метод для него.Таким образом, у вас полностью отключены контроллер и служба уведомлений: контроллеру не нужно сначала создавать тип, и вам также не нужно подписываться на некоторые события (от которых вам также придется отказаться от подписки).в какой-то момент снова, кстати).И вы можете оставить экземпляр полностью в контейнере DI.
Чтобы ответить на ваши индивидуальные вопросы:
Можно ли использовать EntityEntry и EntityState в аргументах события?
Я бы не использовал его в контексте вне вашей базы данных.И то, и другое является реализацией вашей настройки базы данных, так как вы используете Entity Framework здесь.Мало того, что это будет сильно связывать ваши обработчики событий с Entity Framework (а это означает, что каждый, кто хотел бы быть обработчиком событий, должен будет ссылаться на EF, даже если он ничего не делал с ним), вы также утечка, возможно, внутреннего состояния, которое может изменитьсяпозже (вы не владеете EntityEntry
, поэтому кто знает, что EF делает с ним впоследствии).
для каждой измененной записи, я могу получить _dbContext.Entry(modifiedEntry).Properties.Where(x => x.IsModified).ToList();
Если вы посмотрите на свой код, вы сначала наберете Add
, Update
или Remove
для набора вашей базы данных;и затем вы используете некоторую логику, чтобы взглянуть на некоторые внутренние EF вещи, чтобы выяснить точно то же самое на самом деле.Вы могли бы сделать это намного менее сложным, если бы вы сконструировали AppointmentChangeEventArgs
в этих трех switch
случаях напрямую.
, но относится ли это к классу NotificationService?Для этого мне также нужно передать DbContext в NotificationService.
Имеет ли служба уведомлений какое-либо отношение к базе данных?Я бы сказал нет;если вы не сохраняете эти уведомления в базе данных.Когда я думаю о службе уведомлений, я ожидаю, что смогу вызвать что-то для нее, чтобы активировать уведомление, вместо того, чтобы иметь какую-то логику в службе, чтобы выяснить, какие уведомления она может вызвать.
Может ли быть более простой способ добиться этого?Добавлять и удалять обработчики легко («Пользователь X добавил | удалено ... назначение {Заголовок}»), но чтобы выяснить точные изменения, мне нужно взглянуть на измененные свойства.
Сначала подумайте об этом самым простым способом: где вы обновляете значения объекта базы данных?В этом update
случае.Поэтому в тот момент, когда вы копируете значения из переданного объекта, вы также можете просто проверить, какие свойства вы на самом деле меняете.И с этим вы можете легко записать, о каких свойствах вам нужно уведомлять.
Полностью отделите это от EF, и вы будете намного более гибкими в долгосрочной перспективе.