Отслеживание изменений в Entity Framework 4.0 с использованием динамических прокси POCO в нескольких контекстах данных

Если главная цель сохранения пользовательских компонентов на стороне серверов - это иметь возможность показывать один и тот же интерфейс пользователю - почему бы не сохранить всю описательную информацию, необходимую вам о компонентах пользователей, и когда это необходимо - просто снова перестроить пользовательский интерфейс, используя хранимую описательную информацию? Вот пример:

/* That is the class for storing information, which you need from your components*/
 public class DropedComponentsCoordinates implements Serializable{
private String componentID;
private String x_coord;
private String y_coord;
//and so on, whatever you need to get from yor serializable objects;
//getters and setters are assumed but not typed here.
 }

 /* I assume a variant with using FXML. If you don't - the main idea does not change*/
 public class YourController implements Initializable {

List<DropedComponentsCoordinates> dropedComponentsCoordinates;

@Override
public void initialize(URL url, ResourceBundle rb) {
    dropedComponentsCoordinates = new ArrayList();
}

//This function will be fired, every time 
//a user has dropped a component on the place he/she wants
public void OnDropFired(ActionEvent event) {
    try {
        //getting the info we need from components
        String componentID = getComponentID(event);
        String component_xCoord = getComponent_xCoord(event);
        String component_yCoord = getComponent_yCoord(event);

        //putting this info to the list
        DropedComponentsCoordinates dcc = new DropedComponentsCoordinates();
        dcc.setX_Coord(component_xCoord);
        dcc.setY_Coord(component_yCoord);
        dcc.setComponentID(componentID);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

private String getComponentID(ActionEvent event){
    String componentID;
    /*getting cpmponentID*/
    return componentID;
}
private String getComponent_xCoord(ActionEvent event){
    String component_xCoord;
    /*getting component_xCoord*/
    return component_xCoord;
}
private String getComponent_yCoord(ActionEvent event){
    String component_yCoord;
    /*getting component_yCoord*/
    return component_yCoord;
}
}
11
задан Rob Packwood 15 April 2010 в 01:17
поделиться

3 ответа

Как вы заявили позже, вы использовали генератор POCO, а не генератор самонастраивающихся сущностей.

Я тоже пробовал и очень озадачился. Кажется, что прокси-классы работают не совсем так, как ожидалось, и может быть ошибка. Затем снова. ни один из примеров в MSDN не пытается сделать что-то подобное, и когда они ссылаются на обновления на разных уровнях приложения (что-то вроде того, что мы делаем здесь), они используют сущности с самопроверкой, а не прокси-серверы POCO.

Я не уверен, как работают эти прокси, но похоже, что они хранят какое-то состояние (мне удалось найти состояние «Изменено» в частных свойствах). Но похоже, что это свойство ПОЛНОСТЬЮ игнорируется. Когда вы присоединяете свойство к контексту, контекст добавляет запись в ObjectStateManager и сохраняет там дальнейшие обновления состояния. На этом этапе, если вы внесете изменение - оно будет зарегистрировано и применено.

Проблема в том, что когда вы прикрепляете сущность - измененное состояние из прокси не передается в диспетчер состояний внутри контекста. Более того, если вы используете context.Refresh (), обновления отменяются и забываются! Даже если вы передадите в него RefreshMode.ClientWins.Я попытался установить для свойства состояния объекта значение измененное, но оно все равно было переопределено, и исходные настройки были восстановлены.

Похоже, что в EF нет ошибки, и единственный способ сделать это - это используйте что-то вроде этого:

using (var db = new Entities())
{
    var newUser = (from u in db.Users
                    where u.Id == user.Id
                    select u).SingleOrDefault();
    db.Users.ApplyCurrentValues(user);
    db.SaveChanges();
}

Здесь еще кое-что

Entitity Framework: отслеживание изменений в SOA с подходом POCO

Похоже, что POCO просто не поддерживает подход, который вы ищете, и, как я ожидал, Само-отслеживающие объекты были созданы, чтобы справиться с ситуацией, которую вы тестировали, в то время как прокси-серверы POCO отслеживают изменения только в контексте, который они создали ... Или так кажется ...

8
ответ дан 3 December 2019 в 08:03
поделиться

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

В этом случае измените код «сохранения» на следующий:

using (var dataContext = new DataContext())
{
    dataContext.Stores.ApplyChanges(testStore);
    dataContext.SaveChanges();        
}

По крайней мере, я протестировал его на своем локальном компьютере, и он работал после этого обновления :)
Надеюсь, это поможет!

2
ответ дан 3 December 2019 в 08:03
поделиться

Попробуйте

        db.ObjectStateManager.ChangeObjectState(user, System.Data.EntityState.Modified);

Перед вызовом SaveChanges

5
ответ дан 3 December 2019 в 08:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: