И проект A, и проект B являются ASP NET приложениями Core 2.2.
Проект B использует Hangfire для фоновых заданий и почти ничего не делает, а тот факт, что он использует Hangfire, может даже не быть важно (подробнее об этом внизу). Проект A ставит задания в очередь на Hangfire B.
Теперь предположим, что у меня есть класс, представляющий задачу, которая называется Job. Это содержится в проекте C, простой старой библиотеке классов, на которую ссылается проект B, и которая, в свою очередь, ссылается на другие проекты, содержащие объекты, с которыми он работает.
Зависимости должны быть введены в этот класс через конструктор :
public class Job
{
public Job(UserManager<ApplicationUser> userManager,
IThisRepository thisRepository,
IThatRepository thatRepository)
{
}
public void Execute(string userId)
{
// this is where the work gets done
}
}
и по большей части они делают вводятся: IThisRepository
и IThatRepository
вводятся, и они работают ... в основном.
В Проект B Startup.cs
, тот, который должен запускать это задание, я вручную и успешно зарегистрировал эти интерфейсы вместе с DbContext
, для которых им требуются некоторые другие вещи.
UserManager был немного сложнее регистрироваться вручную из-за всех параметров, требуемых его конструктором, поэтому, поскольку мне действительно он не нужен в моей работе, я просто решил внести несколько изменений.
Теперь пример сущностей, с которыми я работаю, выглядит следующим образом:
public class Category
{
[Key]
public int Id { get; set; }
// several other properties of primitive types
public ApplicationUser User { get; set; }
[Required]
public string UserId { get; set; }
}
public class Dish
{
[Key]
public int Id { get; set; }
// several other properties of primitive types
public ApplicationUser User { get; set; }
[Required]
public string UserId { get; set; }
public Category Category { get; set; }
[Required]
public string CategoryId { get; set; }
}
теперь проблема в следующем: внутри Job я пытаюсь создать новый Di sh и связать его с обоими пользователь и категория. Поскольку у меня есть только идентификатор пользователя и нет доступа к UserManager
, я пытаюсь сделать вот что:
// ...
var category = await categoryRepository.FindByUserAndCode(userId, "ABC");
// this is a category that is guaranteed to exist
var dish = new Dish();
dish.UserId = userId;
// notice there's no dish.User assignment, because I don't have an ApplicationUser object
dish.Category = category;
dishRepository.Upsert(dish); (which internally either creates a new entity or updates the existing one as appropriate)
, и здесь все ломается, потому что там написано, что категория с тем же идентификатором, который я пытаюсь вставить, уже присутствует, поэтому я пытаюсь продублировать первичный ключ.
Поскольку категория с кодом AB C для этого пользователя существует в базе данных, я подумал, что это странно.
Вот в чем дело: экземпляр Category
, который возвращает репозиторий, действительно имеет заполненное свойство UserId
, но свойство User
равно null
.
Я думаю, что это причина моей проблемы: EF, вероятно, видит, что свойство - null
, и считает этот объект новым.
Я не знаю, почему он появляется null
(и он даже для других сущностей, у всех которых есть свойство, ссылающееся на пользователя), но я попытался вернуться и, вместо того, чтобы использовать только идентификатор пользователя, я хотел попытаться заставить Hangfire создать экземпляр Job
, вводя в него UserManager<ApplicationUser>
, поэтому по крайней мере, я мог получить экземпляр моего пользователя по его идентификатору.
Стоит отметить, что это работает и в других частях проекта A, просто когда я выполняю фоновое задание, что-то идет ужасно неправильно, и я не могу понять что это такое.
Однако зависимости UserManager
многочисленны, и я боюсь, что могу лаять не на то дерево или делать это совершенно неправильно.
Я сказал, что факт, что я ' m с использованием Hangfire может не иметь значения, потому что предположение, при котором он работает: просто дайте мне имя вашего класса, я позабочусь о его создании , пока все зависимости были зарегистрированы.
Кто-нибудь делал это раньше и может помочь пролить свет?