Добавление записи со связанным дочерним объектом в Entity Framework с использованием шаблона репозитория - PullRequest
0 голосов
/ 06 января 2020

У меня проблемы с добавлением объекта в базу данных, которая содержит отношение к существующему объекту. Я много искал и не мог найти правильное решение для этого. Я опишу это настолько просто, насколько смогу.

public class Store : IEntity
{
    public int StoreId { get; set; }
    public string StoreName { get; set; }

    public virtual Address Address { get; set; }

    public virtual Contractor Contractor { get; set; }
}

    public class Product : IEntity
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public virtual Store Store { get; set; }
}

И в репозитории я добавляю записи вроде этой. Это обобщенно c class

        public TEntity Add(TEntity entity)
    {
        using (var context = new TContext())
        {
            var addedEntity = context.Entry(entity);
            addedEntity.State = EntityState.Added;
            context.SaveChanges();
            return entity;
        }
    }

Теперь, когда я пытаюсь добавить новую запись, подобную этой,

var store = storeManager.GetBy(x => x.StoreId == 1);

var product = new Product() { ProductName = "Bananas", Store = store }; 

productManager.Add(product);

productManager.GetAll().ForEach(x => Console.WriteLine(x.ProductName + " " + x.Store.StoreId));

Отношение магазина добавляется как новый магазин, и он получает новый идентификатор. У кого-то есть идеи, как я могу решить это?

Пример из базы данных:

StoreId StoreName   Address_AddressId   Contractor_ContractorId
1   NULL    1   1
2   NULL    2   2
3   NULL    3   3
4   NULL    4   4
5   NULL    5   5
6   NULL    6   6
7   NULL    7   7

Это мой первый вопрос по stackoverflow.

1 Ответ

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

Наиболее вероятная причина вашей проблемы в том, что вы создаете новый экземпляр вашего контекста для операции вставки. Из-за этого этот новый контекст не только получает новый продукт, но и магазин, который получен из другого контекста, но этот новый созданный контекст не имеет ни малейшего представления, что магазин уже находится в базе данных.

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

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

public class StoreManager
{
     public StoreManager( Context context )
     {
         this.context = context;
     }

   public TEntity Add(TEntity entity)
   {
        var addedEntity = context.Entry(entity);
        addedEntity.State = EntityState.Added;
        context.SaveChanges();
        return entity;
    }
}

Оркестровка должна сначала создать контекст и убедиться, что он разделен между двумя менеджерами

var context = new DbContext();

var storeManager   = new StoreManager( context );
var productManager = new ProductManager( context );

var store = storeManager.GetBy(x => x.StoreId == 1);
var product = new Product() { ProductName = "Bananas", Store = store }; 

productManager.Add(product);

productManager.GetAll().ForEach(x => Console.WriteLine(x.ProductName + " " + 
    x.Store.StoreId));

Обычно все они создаются в одной области, например, в запросе область видимости, так что один веб-запрос имеет один контекст базы данных и каждый репозиторий получает один и тот же экземпляр контекста.

Вы также можете следовать официальному учебнику .

...