Сильно типизированный ASP.NET MVC с Entity Framework - PullRequest
2 голосов
/ 23 мая 2009

Этот код не может фактически сохранить любые изменения:

//
// POST: /SomeType/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
    db.AttachTo(Model.GetType().Name, Model);
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

ASP.NET MVC создает объектную модель в виде типа объекта EntityObject со значением EntityState Отдельно .

После использования метода AttachTo его EntityState становится неизменным .

MSDN о присоединении объектов (Entity Framework)

Объекты прикреплены к объекту контекст в неизменном состоянии.

Из-за состояния неизменного метод ApplyPropertyChanges ничего не делает.

Я хочу, чтобы вместо этого было состояние Изменено .

MSDN при перечислении EntityState

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

Без изменений
Объект не был изменен, так как он был загружен в контекст или с последнего раза что метод SaveChanges был называется.

Модифицированный
Объект изменен, но метод SaveChanges не имеет был назван.

Я не могу явно установить для свойства EntityObject EntityState значение Изменено . Только для чтения.

Разве невозможно иметь строго типизированные контроллеры MVC с EntityObjects?

Ответы [ 5 ]

8 голосов
/ 23 мая 2009

Вам необходимо получить ObjectStateManager из вашего ObjectContext. С ObjectStateManager вы можете явно установить состояние для вашего объекта без необходимости вызывать базу данных:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
    db.AttachTo(Model.GetType().Name, Model);

    ObjectStateManager stateMgr = db.ObjectStateManager;
    ObjectStateEntry stateEntry = stateMgr.GetObjectStateEntry(model);
    stateEntry.SetModified(); // Make sure the entity is marked as modified
    //db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);

    db.SaveChanges();
    return RedirectToAction("Index");
}

ObjectStateEntry также позволяет вам применять более тонкие данные об изменении состояния через SetModifiedProperty. Если вы вызываете SetModified, EF будет обрабатывать всю сущность как измененную и сохранять каждое свойство в хранилище данных. С помощью SetModifiedProperty EF может оптимизировать запросы и использовать только те свойства, которые действительно изменились. Использование SetModifiedProperty, очевидно, более сложное, так как обычно вам нужно знать исходное значение каждого свойства.

Надеюсь, это поможет. ObjectStateManager является мощным небольшим инструментом в наборе инструментов EF и может помочь улучшить и в других случаях EF v1.0.

3 голосов
/ 19 октября 2009

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

Второй пример:

http://msdn.microsoft.com/en-us/library/bb896248.aspx#Mtps_DropDownFilterText

private static void ApplyItemUpdates(SalesOrderDetail updatedItem){
// Define an ObjectStateEntry and EntityKey for the current object.
EntityKey key;
object originalItem;

using (AdventureWorksEntities advWorksContext =
    new AdventureWorksEntities())
{
    try
    {
        // Create the detached object's entity key.
        key = advWorksContext.CreateEntityKey("SalesOrderDetail", updatedItem);

        // Get the original item based on the entity key from the context
        // or from the database.
        if (advWorksContext.TryGetObjectByKey(key, out originalItem))
        {
            // Call the ApplyPropertyChanges method to apply changes
            // from the updated item to the original version.
            advWorksContext.ApplyPropertyChanges(
                key.EntitySetName, updatedItem);
        }

        advWorksContext.SaveChanges();
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

}

1 голос
/ 20 октября 2009

У меня это работает, но я не могу найти родительскую сущность SalesOrderDetail Как я могу получить это?

SalesOrderDetail.SalesOrderHead имеет значение NULL, а также ссылка на объект имеет значение NULL. Моя подпрограмма редактирования имеет доступ только к идентификатору SalesOrderDetail.

Спасибо Sri

1 голос
/ 23 мая 2009

Что произойдет, если вы добавите одну строку:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
    db.AttachTo(Model.GetType().Name, Model);
    Model.SomeProperty = Model.SomeProperty; // This looks hacky... =(
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

Состояние меняется?

1 голос
/ 23 мая 2009

Это работает:

//
// POST: /SomeType/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
    Model.EntityKey = (from SomeType s in db.SomeType
                       where s.Id == id
                       select s).FirstOrDefault().EntityKey;
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

Но есть ли способ без запроса базы данных?

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