POCO в Entity Framework с обнаружением изменения снимка - PullRequest
2 голосов
/ 03 марта 2010

У меня есть Visual Studio 2010 сгенерированный набор классов POCO (только из коробки шаблоны POCO, сгенерированные из схемы БД). Для данного варианта использования я позволяю пользователю загрузить объект (контакт CRM) и действовать на него - добавить номера телефона (который сам по себе является отдельным объектом, связанным внешним ключом) и адрес (также отдельный объект) и т. Д. Между postbacks Я сохраняю измененные сущности во ViewState (я не хочу сохранять изменения в базе данных сразу). Проблема возникает, когда пользователь нажимает кнопку Сохранить. Основной контакт CRM будет сохранен нормально (любые изменения обнаружены и сохранены), но ни одно из связанных свойств не будет сохранено - независимо от того, является ли это новым дополнением или измененным EF, просто игнорирует его.

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

//contact is an instance of CRMContact retrieved from ViewState
if (contact.Id == 0) {
    CRMEntities.CRMContacts.AddObject(contact);
} else {
    CRMContact orig = CRMEntities.CRMContacts.Where(c => c.Id == contact.Id).FirstOrDefault();
    CRMEntities.CRMContacts.ApplyCurrentValues(contact);
}

CRMEntities.SaveChanges(SaveOptions.DetectChangesBeforeSave | SaveOptions.AcceptAllChangesAfterSave);

Это нормально работает для контактной сущности, но не для моих связанных. Что мне нужно добавить для телефонных номеров и электронных писем, которые будут добавлены и / или обновлены?

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

Спасибо

Ответы [ 2 ]

2 голосов
/ 04 марта 2010

После долгих проб и ошибок мне удалось собрать что-то, что работает. Обратите внимание, что я понятия не имею, если это правильный способ сделать это. Это код из другой части проекта. IAHeader является основным объектом, IAAttachment и IAComment оба связаны с заголовком внешним ключом:

public static void Save(IAHeader head) {
    IAHeader orig = new IAHeader();
    if (head.Id == 0) {
        IAData.Entities.IAHeaders.AddObject(head);
    } else {
        orig = IAData.Entities.IAHeaders.Where(h => h.Id == head.Id).FirstOrDefault();
        IAData.Entities.IAHeaders.ApplyCurrentValues(head);

        foreach (IAComment comm in head.Comments.ToList()) {
            if (comm.Id == 0) {
                comm.IAHeader = null; //disassociate this entity from the parent, otherwise parent will be re-added
                comm.IAId = head.Id;
                IAData.Entities.IAComments.AddObject(comm);
            } else {
                IAComment origComm = orig.Comments.Where(c => c.Id == comm.Id).First();
                IAData.Entities.IAComments.ApplyCurrentValues(comm);
            }
        }

        foreach (IAAttachment att in head.Attachments.ToList()) {
            if (att.Id == 0) {
                att.IAHeader = null; //disassociate this entity from the parent, otherwise parent will be re-added
                att.IAId = head.Id;
                IAData.Entities.IAAttachments.AddObject(att);
            } else {
                IAAttachment origAtt = orig.Attachments.Where(a => a.Id == att.Id).First();
                IAData.Entities.IAAttachments.ApplyCurrentValues(att);
            }
        }
    }
    IAData.Entities.SaveChanges(SaveOptions.DetectChangesBeforeSave | SaveOptions.AcceptAllChangesAfterSave);
}

Очевидно, что можно сделать много улучшений, но это то, что я придумал, что подходит для моего сценария. Важная часть, которая меня больше всего путала, - это необходимость отсоединять мои навигационные свойства от моей основной сущности, в противном случае я либо получу ошибку «ключ сущности уже существует», либо основная сущность будет сохранена дважды.

0 голосов
/ 03 марта 2010

Я не вижу, где вы изменили какие-либо связанные значения. Документы для ObjectContext.ApplyCurrentValues ​​ говорят:

Копирует скалярные значения из предоставленного объекта в объект в ObjectContext с тем же ключом.

(выделение добавлено).

Поскольку вы не внесли никаких других изменений, я бы сказал, что нечего обнаруживать.

...