Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обновить данные в базе, LINQ 
:(
    Опции темы
KLUBS
Дата 21.12.2008, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 11.2.2007
Где: Спб

Репутация: нет
Всего: 1



Привет.

Подскажите, пожалуйста, как можно обновить LINQ класс как объект.. Звучит глупо, но:

Код

public static void UpdateCustomer(Customer customer)
        {
            MyDataContext dataContext = new MyDataContext();
            //dataContext.DeferredLoadingEnabled = false;
            Customer cus = (from p in dataContext.Customers where p.Id == customer.Id select p).Single();


            //Как можно обновить объект cus, вручную не меняя поля cus
            cus = customer;


           // dataContext.Customers.Attach(cus);
           // dataContext.SubmitChanges();

            //MyDataContext dataContextSave = new IMyDataContext();
            //dataContextSave.Customers.Attach(customer, cus);
            //dataContextSave.SubmitChanges();
        }


Это сообщение отредактировал(а) KLUBS - 21.12.2008, 01:09
PM MAIL ICQ Skype   Вверх
KLUBS
Дата 21.12.2008, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 11.2.2007
Где: Спб

Репутация: нет
Всего: 1



Чем больше поллей в таблице, тем больше полей нужно обновлять руками, если изменяешь структуру таблицы.. то все летит..
PM MAIL ICQ Skype   Вверх
PashaPash
Дата 21.12.2008, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 4
Всего: 49



KLUBS
Код

MyDataContext dataContext = new MyDataContext();
dataContext.Customers.Attach(customer);
dataContext.SubmitChanges();

http://blogs.msdn.com/dinesh.kulkarni/arch...g-detached.aspx
если нужен concurrency, то просто вызова Attach(customer, cust) должно хватить.

Это сообщение отредактировал(а) PashaPash - 21.12.2008, 16:58


--------------------
PM MAIL WWW   Вверх
KLUBS
Дата 21.12.2008, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 11.2.2007
Где: Спб

Репутация: нет
Всего: 1



В том то и дело, что не получается. 
этот метод вызывает исключение: 
Код

dataContext.Customers.Attach(customer);

An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext

Вроде решил, сделал DataContext - статическим для всего класса, и теперь, при обновлении просто пишу dataContext.SubmitChanges();

Так нормально?)
PM MAIL ICQ Skype   Вверх
PashaPash
Дата 23.12.2008, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 4
Всего: 49



KLUBS, это плохое решание - практически, ты загружаешь в память полную копию базы.
Вообще проблема в том, что твой Customers ссылается на другие объекты, и для них срабатывает Deferred Loading - вмест объектов передаются незагруженные EntityRef. При попытке их сохранить все и падает. Решение - отключить DeferredLoading у оригинального контекста, тогда объект Customer будет существовать сам по себе.
Код

            Customer customerToChange, originalCustomer;
            using (DataClasses1DataContext context1 = new DataClasses1DataContext())
            {
                context1.DeferredLoadingEnabled = false;
                context1.ObjectTrackingEnabled = false;

                customerToChange = context1.Customers.SingleOrDefault();
                originalCustomer = context1.Customers.SingleOrDefault();
            }

            customerToChange.SomeProperty = "ddd";

            using (DataClasses1DataContext context3 = new DataClasses1DataContext())
            {
                context3.Customers.Attach(customerToChange, originalCustomer);
                context3.SubmitChanges();
            }

Если не хочешь таскать с собой по коду originalCustomer - его можно выбирать прямо перед аттачем
Код

            Customer customerToChange;
            using (DataClasses1DataContext context1 = new DataClasses1DataContext())
            {
                context1.DeferredLoadingEnabled = false;
                context1.ObjectTrackingEnabled = false;

                customerToChange = context1.Customers.SingleOrDefault();
            }

            customerToChange.SomeProperty = "ddd3";

            Customer originalCustomer;
            using (DataClasses1DataContext context2 = new DataClasses1DataContext())
            {
                context2.DeferredLoadingEnabled = false;
                context2.ObjectTrackingEnabled = false;

                originalCustomer = context2.Customers.SingleOrDefault();
            }

            using (DataClasses1DataContext context3 = new DataClasses1DataContext())
            {
                context3.Customers.Attach(customerToChange, originalCustomer);
                context3.SubmitChanges();
            }

Но лучше добавить в таблицу Customers поле c типом timestamp, можно будет делать прямо так:
Код

            Customer customerToChange;
            using (DataClasses1DataContext context1 = new DataClasses1DataContext())
            {
                context1.DeferredLoadingEnabled = false;
                context1.ObjectTrackingEnabled = false;

                customerToChange = context1.Customers.SingleOrDefault();
            }

            customerToChange.SomeProperty = "ddd1";

            using (DataClasses1DataContext context3 = new DataClasses1DataContext())
            {
                context3.Customers.Attach(customerToChange, true);
                context3.SubmitChanges();
            }



--------------------
PM MAIL WWW   Вверх
KLUBS
Дата 23.12.2008, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 11.2.2007
Где: Спб

Репутация: нет
Всего: 1



PashaPash
первые 2 понятно.
Дело в том, что я делаю выборку из бд, пихаю ее в ListBox.DataContext потом, пользователь нажимает кнопку изменить, открывается окошко и в это окошко DataContext присваивается элемент этого ListBox'a (ListBox.SelectedValue as Customers). (+ ко всему все это на привязке данных)
Если я хочу изменить Весь объект Customers сразу, как мне быть?

1. обновить все поля вручную. Можно, но мне очень не нравится такой вариант, потому что при изменения чего то придется менять код этого места.

2. Attach(); вот тут то и начинается веселье. Он говорит, что не может обновить элемент, т.к. он получен из другого DataContext'a... еще часик покопавшись в нете, нашел вот этот метод решения этой задачи:

Код

 private static Data.Customer UpdateCustomerInfo(Data.Customer newCustomer, Data.Customer old)
        {
            foreach (PropertyInfo property in newCustomer.GetType().GetProperties())
            {
                PropertyInfo orignP = old.GetType().GetProperty(property.Name);
                orignP.SetValue(old, property.GetValue(newCustomer, null), null);
            }

            return old;
        }

PM MAIL ICQ Skype   Вверх
PashaPash
Дата 23.12.2008, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 4
Всего: 49



Цитата(KLUBS @  23.12.2008,  18:16 Найти цитируемый пост)
2. Attach(); вот тут то и начинается веселье. Он говорит, что не может обновить элемент, т.к. он получен из другого DataContext'a... еще часик покопавшись в нете, нашел вот этот метод решения этой задачи:

Я ж специально написал - отключить DeferredLoading у оригинального контекста, тогда объект Customer будет существовать сам по себе. В первом примере. context.DeferredLoadingEnabled = false;, может быть еще ObjectTrackingEnabled = false.
Я же проверил код, перед тем как постить - он точно не падает, и все вполне сохраняется без рефлекшена и прочих хаков.


--------------------
PM MAIL WWW   Вверх
namespace
  Дата 12.1.2009, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 70
Регистрация: 4.7.2006

Репутация: нет
Всего: нет



а помимо DeferredLoadingEnabled = false и повторной выборки из контекста в котором будет вызван SubmitChanges() есть способы изменить объект не из этого контекста? ведь это же не рационально имея объект еще раз нагружать сервер, плюс трафик, по моему мелкософт схалтурил 
PM MAIL   Вверх
PashaPash
Дата 13.1.2009, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 4
Всего: 49



Цитата(namespace @  12.1.2009,  23:58 Найти цитируемый пост)
а помимо DeferredLoadingEnabled = false и повторной выборки из контекста в котором будет вызван SubmitChanges() есть способы изменить объект не из этого контекста? ведь это же не рационально имея объект еще раз нагружать сервер, плюс трафик, по моему мелкософт схалтурил  

DeferredLoadingEnabled - это отложенная загрузка полей-ссылок. Чтобы она работала, объект должен быть привязан к датаконтексту. Для того, чтобы объект существовал сам по себе, его нужно явно оторвать он начального контекста (варианты с Detach, много в гугле), или просто не привязывать с самого начала (=false).
Без повторной выборки - смотри 3-й вариант, там без повторной выборки. "Нерациональная загрузка" обычно называется Optimistic Concurrency, и ей можно вполне нормально управлять, или вообще отключить, расставив UpdateCheck.None на колонках. Но для этого надо представлять последствия для конкретного приложения, и общий механизм работы change traсking-a, а не считать его халтурой microsoft. Авторы nHibernate и других нормальных ORM тоже подхалтуривают, судя по всему smile


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | LINQ (Language-Integrated Query) | Следующая тема »


 




[ Время генерации скрипта: 0.0931 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.