Entity Framework и Entity Tracker Проблемы - PullRequest
0 голосов
/ 17 июня 2009

Если я запускаю следующий код, он выдает следующую ошибку:

На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker

 public void Save(Category category)
        {
            using(var db = new NorthwindContext())
            {
                if(category.CategoryID == 0) 
                {
                    db.AddToCategorySet(category); 
                }

                else
                {
                    //category.RemoveTracker();
                    db.Attach(category);
                }

                db.SaveChanges(); 
            }
        } 

Причина, конечно, в том, что категория отправляется из интерфейса, который мы получили из метода GetById, который уже прикрепил EntityChangeTracker к объекту категории. Я также попытался установить нулевой трекер сущностей, но он не обновил объект категории.

  protected void Btn_Update_Category_Click(object sender, EventArgs e)
        {
            _categoryRepository = new CategoryRepository();
            int categoryId = Int32.Parse(txtCategoryId.Text);

            var category = _categoryRepository.GetById(categoryId);

            category.CategoryName = txtUpdateCategoryName.Text; 

            _categoryRepository.Save(category);
        }

1 Ответ

0 голосов
/ 17 июня 2009

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

public void Save(Category category)
{
    using (var db = new NorthwindContext())
    {
        ...
    }
}

... в вашем методе доступа к данным. Вы делали то же самое в вашем GetById методе? Если да, помните ли вы, чтобы отсоединить полученный объект, чтобы он мог быть присоединен позже в другом контексте?

public Category GetById(int categoryId)
{
    using (var db = new NorthwindContext())
    {
        Category category = (from c in db.Category where Category.ID == categoryId select c).First();
        db.Detach(category);
    }
}

Таким образом, когда вы звоните Attach, он не пытается наступить на уже подключенный контекст. Это помогает?

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

  1. Если ваша архитектура поддерживает это, вы можете расширить область своего контекста настолько, чтобы ваш метод Save мог использовать тот же контекст, что и ваш метод GetById. Это помогает полностью избежать проблемы присоединения / отсоединения, но может подтолкнуть уровень данных немного ближе к вашей бизнес-логике, чем вы хотели бы.
  2. Вы можете загрузить новый экземпляр элемента из нового контекста на основе его идентификатора, установить все его свойства на основе переданной категории и затем сохранить его. Это потребует двух обращений к базе данных для того, что действительно нужно только одному, и это не очень поддерживаемо.
  3. Вы можете копаться в самом контексте, чтобы пометить свойства категории как измененные.

Например:

public void Save(Category category)
{
    using (var db = new NorthwindContext())
    {
        db.Attach(category);
        var stateEntry = db.ObjectStateManager.GetObjectStateEntry(category);
        foreach (var propertyName in stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(fm => fm.FieldType.Name)) {
            stateEntry.SetModifiedProperty(propertyName);
        }
        db.SaveChanges();
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...