Объекты теряют отслеживание изменений при редактировании с помощью MVC3 - PullRequest
1 голос
/ 14 февраля 2012

Я создал очень простое приложение MVC3, чтобы сделать небольшую демонстрацию, но я работаю с проблемой;Я возвращаю сущность в свое представление, редактирую ее и затем публикую обратно, но в этом процессе моя сущность теряет свои возможности отслеживания изменений.Когда я возвращаю сущность в свое представление, это все еще прокси-класс структуры сущности, но когда он возвращается из моего представления, это класс «Person» (сущность называется person).

Вот мой класс хранилища:

public class PersonRepository : IPersonRepository
{
    public EfContext Uow { get; set; }

    public PersonRepository(IUnitOfWork uow)
    {
        Uow = uow as EfContext;
    }

    // yada yada yada

    public void Add(Person person)
    {
        Uow.Persons.Add(person);
    }
}

Эта сущность отправлена ​​на мой взгляд в простой форме, созданной с помощью Html.EditorForModel.После этого я отправляю его обратно к этому методу:

[HttpPost]
public ActionResult Edit(Person person)
{
    if (ModelState.IsValid)
    {
        _personRepository.Add(person);
        _personRepository.Uow.Commit();

        return RedirectToAction("Index");
    }

    return View(person);
}

И тада, это уже не отслеживаемый прокси-класс.Это приводит к нарушению первичного ключа, потому что структура сущностей пытается добавить мой объект как новый объект, где я просто хочу, чтобы структура сущностей обнаружила изменения и вместо этого создала оператор обновления.О, кстати, метод Commit в коде выше просто вызывает SaveChanges (), вот класс:

public class EfContext : DbContext, IUnitOfWork
{
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Person> Persons { get; set; } 

    public void Commit()
    {
        SaveChanges();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Кстати, это мой класс сущности:

public class Person
{
    [HiddenInput(DisplayValue = false)]
    public Guid Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public virtual ICollection<Account> Accounts { get; set; } 
}

Кто-нибудь знает, как это исправить?У меня это работало раньше, насколько я помню, я просто не знаю, как.

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 14 февраля 2012

Я предполагаю, что вы создаете свой репозиторий для каждого запроса (в конструкторе или передаются в качестве зависимости вашей средой IoC или чем-то еще). В этом случае сущность, которую вы получаете в вашем методе контроллера, действительно не отслеживается, потому что она была создана в другом запросе. Вы должны «прикрепить» его к контексту и пометить его как измененный, чтобы EF знал, что он изменился, и его необходимо сохранить в БД

1 голос
/ 14 февраля 2012

Определите метод Update в вашем хранилище, который будет прикреплять объект и помечать его как измененный.

public class PersonRepository : IPersonRepository
{
    // yada yada yada

    public void Add(Person person)
    {
        Uow.Persons.Add(person);
    }

    public void Update(Person person)
    {
        Uow.Persons.Attach(person);
        Uow.Entry(person).State = EntityState.Modified;
    }
}

[HttpPost]
public ActionResult Edit(Person person)
{
    if (ModelState.IsValid)
    {
        _personRepository.Update(person);
        _personRepository.Uow.Commit();

        return RedirectToAction("Index");
    }

    return View(person);
}
0 голосов
/ 14 февраля 2012

Здесь есть третье решение, которое, я считаю, является наиболее отказоустойчивым.

Вы можете настроить действие MVC для получения целого числа id.Затем, используя это целое число, вы извлекаете сущность из базы данных.Затем вы вызываете метод UpdateModel на контроллере.Это свяжет новые значения формы с существующим объектом, но не изменит неизменных свойств и свойств, которые могли отсутствовать в форме.

...