2012-04-09 4 views
3

Я хотел получить некоторые отзывы о ваших мыслях о хранении целых объектов в сеансе? Например, объект клиента. Как только клиент входит в свою панель управления, вместо повторной выборки своих данных каждый раз, когда это необходимо из идентификатора, хранящегося в сеансе, каковы плюсы и минусы сохранения всего объекта клиента в сеансе?Мысли о хранении целых объектов LINQ в сеансе?

Так в любое время вам нужно ссылаться на объект клиента, вы можете просто сделать:

Customer c = (Customer)Session["objCustomer"]; 

Очевидно, что вам нужно будет проверить и есть функция, которая обновляет сеанс. Вам нужно будет запустить эту функцию в случае нулевого сеанса или после создания обновления.

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

+7

Вам нужно быть особенно внимательным, чтобы вы не пытались следовать ленивым свойствам объекта. ИМО, лучше создать объект POCO, содержащий только те свойства, которые вам нужны регулярно, и сохранить их в сеансе, а не весь объект LINQ. – mellamokb

+2

Согласовано. Вам нужен пользовательский объект для хранения вашей работоспособности в приложении, отключенный от фактической базы данных. Вы не хотите, чтобы деревья выражений и свойства с поздней оценкой смешивались с вашей состоятельностью. – David

+0

Что сказал mellamokb. Добавив, что я думаю, что это была бы плохая идея, потому что кто-то, кто за вами после этого, может попытаться сделать что-то вроде обновления объекта и получить ошибки об удаляемом контексте. Метод POCO имеет четко определенные и доступные для поиска механизмы для возврата данных в линию с контекстом, чтобы вы могли воздействовать на него в базе данных. В долгосрочной перспективе это было бы менее вонючим в приложении. – Felan

ответ

7

Это не очень хорошая идея.

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

Лично я предпочитаю подход, когда простой объект, содержащий идентификатор клиента (и, возможно, другие атрибуты), хранится в сеансе (или в разделе пользовательских данных в файле cookie), и я завершаю доступ к объекту клиента в простое заявление, которое включает в себя Items контейнера:

(производство коды потребовалась бы несколько проверок здесь и там, чтобы быть более оборонительными):

const string CUSTOMERITEM = "customeritem"; 
public Customer Current 
{ 
    get 
    { 
     if (HttpContext.Current.Items[CUSTOMERITEM] == null) 
     { 
      int id = retrieve_the_id; 

      using (DbContext ctx = GetCurrentDbContext()) 
      { 
       HttpContext.Current.Items.Add(CUSTOMERITEM, ctx.Customers.FirstOrDefault(c => c.ID == id); 
      } 
     } 
     return (Customer)HttpContext.Current.Items[CUSTOMERITEM]; 
    } 
} 

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

Конечно, это связано с ценой одного дополнительного запроса на запрос по сравнению с вашим подходом. Но преимущество в том, что вы никогда не испортите контексты базы данных.

Обратите внимание, что есть некоторые бизнес-процессы, которые не требуют Customer объекта, но вы можете передать идентификатор клиента непосредственно и использовать в запросах:

public IEnumerable<Order> CustomerOrders(int CustomerID) 
{ 
    // use the customer id directly, without first loading the customer object 
} 
2

я столкнулся с проблемой, описанной на Wiktor в другой ответ. Я использую NHibernate, и если вы храните объекты в сеансе, вы получите проблемы, сравнивающие их, проблемы с отключенными сеансами и т. Д. Тем не менее я продолжаю и сохраняю свои объекты в сеансе. Я просто убеждаюсь, что все они реализуют свои собственные функции Equals() и GetHashCode(). Таким образом, я могу сравнивать объекты с разных сеансов, чтобы увидеть, являются ли они одним и тем же объектом. Я делаю это привычкой использовать obj1.Equals(obj2) вместо obj1 == obj2.

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

0

mellamokb Я согласен с вашей точкой зрения о том, чтобы принести необходимые вам свойства. вы можете это сделать, настроив модель, и вы также можете отключить ленивую загрузку. Кроме этого, я думаю, что это довольно безопасно.Если мы не будем хранить все эти объекты в качестве ссылок, тогда нет никакой проблемы, эти объекты сами по себе будут размещены в сеансе. единственный раз, когда вы можете вызвать проблему, - если оба контекста находятся в области видимости.

Смежные вопросы