Entity Framework: один ко многим? - PullRequest
0 голосов
/ 30 января 2020

Я жонглирую отношениями «один ко многим» с использованием Entity Framework:

Мне нужно вставить группу данных из C# объектов в мою SQL Серверную базу данных, поэтому я использую Entity Framework с подходом Code First.

В моем примере у меня есть продукт, который имеет одну категорию, но категории могут явно принадлежать нескольким продуктам.

Мой класс Product выглядит следующим образом.

    public class Product
    {
    public int ProductId { get; set; }
    public string Name { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
    }

Я пробовал несколько решений для своего класса Category, как с строкой с комментариями, так и без нее, но здесь мы go:

    public class Category
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
 // public ICollection<Product> Products { get; set; }
}

При вставке нескольких продуктов с одинаковыми категория, я получаю нарушение ограничения первичного ключа - что я понимаю, почему происходит, но я думаю, что Entity Framework позаботится о!

У меня есть длинный список индексов, которые я использую, чтобы получить XML - файл (на основе этого индекса) из API. Затем я создаю объект на основе этого XML файла. Метод называется GetProductFrom XML:

Foreach(int index in listOfIndexes){
   Product product = GetProductFromXML(index);
   productContext.Products.Add(product);
 }
Context.SaveChanges();

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

Очевидно, что EF понимает, что второй объект должен использовать категорию из первого объекта.

Что мне делать? Я нахожу это таким простым действием, которое было бы легко сделать с помощью обычных запросов, но с Entity Framework я оборачиваюсь вокруг него, и я схожу с ума!

Надеюсь, кто-то даст мне логи c ответ!

1 Ответ

1 голос
/ 30 января 2020

Вы создаете два новых Category экземпляра и явно присваиваете им одинаковые CategoryId. (Вы также на самом деле не используете ни один экземпляр для своих продуктов, и вы никогда не устанавливаете никаких свойств для второго продукта. Я предполагаю, что это опечатки.)

Создайте только один экземпляр :

Category category = new Category();
category.CategoryId = 1;
category.CategoryName = "categoryA";

Затем используйте его для обоих ваших Product экземпляров:

Product product = new Product();
product.ProductId = 1;
product.Name = "ProductA";
product.Category = category;
context.Products.Add(product);

Product productB = new Product();
productB.ProductId = 2;
productB.Name = "ProductB";
productB.Category = category;
context.Products.Add(productB);

Редактировать: Из длинной ветки комментариев ниже (и обновленного вопроса) который скрывает ошибочный код нового метода), исходная проблема все еще остается ... Вы создаете новые Category экземпляры, в которых вам следует повторно использовать существующие экземпляры.

Рассмотрите возможность сохранения их в списке вне вашего метода. Как логическое руководство, что-то вроде этого:

// Note: If there are categories from previous runs of this logic
//       then you should fetch them from the backing data here
var categories = new List<Category>();

foreach (int index in listOfIndexes)
{
    var product = GetProductFromXML(index, categories);
    productContext.Products.Add(product);
}
Context.SaveChanges();

И вот ваш GetProductFromXML метод:

int id = // ... get the Product ID from your XML
string name = // ... get the Product Name from your XML
//... etc.
string categoryName = // ... get the Category Name from your XML

var category = categories.SingleOrDefault(c => c.Name == categoryName);
if (category = null)
{
    // It doesn't exist yet, so add it
    category = new Category();
    category.Name = categoryName;
    category.CategoryId = // ... whatever logic you use to determine this
    categories.Add(category);
}

return new Product
{
    ProductId = id,
    Name = name,
    // etc.
    Category = category
};
...