Я пытаюсь выставить статические объекты, используя Microsoft.EntityFrameworkCore в .netcoreapp 2.1.
Данные, которые я хочу предоставить, находятся в файле .json, и я могу без проблем десериализовать их в соответствующие классы С#.
Вот пример структуры: https://pastebin.com/SKCKsDJi
Для ясности я предлагаю вам прочитать его, используя ваш любимый читатель json.
А вот версия этих объектов на С#:
public class FoodItem
{
public int Id { get; set; }
public string Name { get; set; }
public FoodType Type { get; set; }
public string Picture { get; set; }
public float Price { get; set; }
public string Currency { get; set; }
public IEnumerable<Ingredient> Ingredients { get; set; }
public bool IsVegetarian { get; set; }
}
public class FoodType
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Ingredient
{
public int Id { get; set; }
public string Name { get; set; }
}
Давайте не будем усложнять, есть ingredients, types и items, предметы в основном представляют собой бутерброды, которые относятся к определенному типу и содержат список ингредиентов. Все 3 имеют идентификаторы, чтобы соответствовать им. В этом и заключается моя проблема, или я так думаю.
Все работает нормально, если я просто использую «Типы», например, в своем dbcontext. Как только я пытаюсь добавить либо ингредиенты, либо предметы, либо все 3 (что мне нужно, но маленькими шагами), у меня возникает следующая ошибка.
InvalidOperationException: The instance of entity type 'Ingredient' cannot be tracked because another instance with the key value '{Id: 1}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
Это происходит, когда:
public EatupController(EatupContext context)
{
_context = context;
var completeModel = JsonConvert.DeserializeObject<EatUpDataModel>(EatUpDataSet.Complete);
_context.Types.AddRange(completeModel.Types); //Works
_context.Ingredients.AddRange(completeModel.Ingredients); //Crashes here.
//If removed, all is fine but data is incomplete
//_context.Types.AddRange(completeModel.Types); //Unused
//_context.Items.AddRange(completeModel.Items); //Unused
_context.SaveChanges();
}
Я не понимаю, почему он жалуется на дубликаты идентификаторов, потому что они все идентичны. За исключением того, что когда я ссылаюсь на ингредиент X в предмете, очевидно, что некоторые предметы будут использовать ингредиенты, используемые другими предметами (во многих бутербродах есть помидоры). Но, конечно, такой тип отношений разрешен.
Сначала у меня были идентификаторы, начинающиеся с 0 для всех различных типов объектов, поэтому ингредиенты варьировались от 0 до примерно 100, предметы от 0 до 60 и типы от 0 до 7. Но поскольку у меня была эта ошибка, я отредактировал все идентификаторы, и я до сих пор есть ошибка, которая очень сбивает с толку.
Из того, что я читал, это также может быть связано с использованием контекста в разных потоках, но это не так. Если я удалю строку, которая падает, она перестает падать, и я могу правильно видеть данные в контексте. В данном случае только виды. Если я добавляю в контекст только предметы или ингредиенты, он вылетает по той же причине, только в другом объекте (ингредиенте или предмете).
Куда мне идти отсюда? У меня даже нет плохого решения, которое я мог бы попытаться реализовать. Моя худшая идея заключалась в том, чтобы вручную изменить идентификаторы (что для меня глупо, это должно работать со старыми), но даже это не удалось.
Нет, и ингредиенты, и типы содержат «id» и «name». И ни один из них не равен. Но даже с этим я бы не согласился, я бы хотел, чтобы идентификаторы моих ингредиентов начинались с 0 и мои типы тоже. В моем SQL мои таблицы всегда начинаются с нуля, даже если другие таблицы начинаются с нуля.
Вы можете посмотреть json в pastebin, чтобы быть предельно ясным в отношении объектных отношений, они отображаются точно так же в С#.
Таким образом, JSON, кстати, содержит несколько дубликатов. в списке items также есть ингредиенты, так что это будет проблемой. Кроме того, почему ингредиенты начинаются с нуля? Не проблема, но это странно, так как позже он может скрыть «пустые» значения.
Они начинаются с нуля без какой-либо причины, они могут начинаться с 1 или 764, я просто предположил, что 0 — хорошее начало для идентификатора. Я могу это изменить (хотя редактирование json - это боль: D). Предметы содержат ингредиенты, потому что они «должны», как и их реальный аналог. Как мне структурировать свои объекты, если я хочу, чтобы мой items состоял из различных ingredients, если не иметь списка этих ingredients как свойства item? Я не хочу, чтобы это было продублировано, но я не вижу, как еще это можно было бы сделать.
У вас должна быть промежуточная таблица для связи ингредиентов и предметов, я бы добавил их как отдельный объект.
Если два продукта питания имеют общий ингредиент, ваш десериализатор JSON предоставит вам два разных объекта Ingredient с одним и тем же ключом.
Хорошо, я понимаю проблему, но как мне тогда справиться с этой ситуацией? Два продукта питания очень часто будут иметь общие ингредиенты. Должен ли я переупорядочить свой json или есть способ «лучше разобрать его»?





Содержат ли
Typesдочерние объекты, которые каким-то образом ссылаются наIngredients?