Если главная цель сохранения пользовательских компонентов на стороне серверов - это иметь возможность показывать один и тот же интерфейс пользователю - почему бы не сохранить всю описательную информацию, необходимую вам о компонентах пользователей, и когда это необходимо - просто снова перестроить пользовательский интерфейс, используя хранимую описательную информацию? Вот пример:
/* 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;
}
}
Как вы заявили позже, вы использовали генератор 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 отслеживают изменения только в контексте, который они создали ... Или так кажется ...
Поигравшись с объектами самопроверки, я понял, в чем была ваша ошибка. Вместо того, чтобы пытаться прикрепить объект к данным context, вы должны вместо этого указать, что вы хотите, чтобы контекст данных применял к базе данных новые изменения, которые вы внесли в него.
В этом случае измените код «сохранения» на следующий:
using (var dataContext = new DataContext())
{
dataContext.Stores.ApplyChanges(testStore);
dataContext.SaveChanges();
}
По крайней мере, я протестировал его на своем локальном компьютере, и он работал после этого обновления :)
Надеюсь, это поможет!
Попробуйте
db.ObjectStateManager.ChangeObjectState(user, System.Data.EntityState.Modified);
Перед вызовом SaveChanges