2010-05-11 2 views
2

Недавно я думал о разнице в производительности между членами класса класса и переменными метода. Что именно я имею в виду в приведенном ниже примере:Члены поля и переменные метода?

позволяет сказать, что у нас есть DataContext объект для Linq2SQL

class DataLayer 
{ 
    ProductDataContext context = new ProductDataContext(); 

    public IQueryable<Product> GetData() 
    { 
     return context.Where(t=>t.ProductId == 2); 
    } 
} 

В приведенном выше примере, контекст будет храниться в куче и GetData метод переменных будет удаляется из Stack after Method.

Итак, давайте рассмотрим следующий пример, чтобы сделать различие:

class DataLayer 
{ 
    public IQueryable<Product> GetData() 
    { 
     ProductDataContext context = new ProductDataContext(); 
     return context.Where(t=>t.ProductId == 2); 
    } 
} 

(* 1) Так хорошо первое, что мы знаем, если мы определим ProductDataContext экземпляр как поле, мы можем достигнуть его везде класс, который означает, что нам не нужно создавать экземпляр объекта все время.

Но скажем, что мы говорим об Asp.NET, и как только пользователи нажимают кнопку отправки, данные отправляются на сервер, а события выполняются, а размещенные данные хранятся в базе данных с помощью вышеописанного метода, так что это вероятно что один и тот же пользователь может отправлять разные данные друг за другом. Если я правильно знаю, что после выполнения страницы, финализаторы начинают играть и очищают вещи от памяти (от кучи), а это значит, что мы теряем наши переменные экземпляра из памяти, а также еще один пост, DataContext должен быть создан еще раз для нового цикла страниц.

Таким образом, это единственное преимущество, заключающееся в том, чтобы публично объявить его всем классом - это текст только одного номера выше.

Или есть что-то другое?

Заранее спасибо ...

(Если я сказал что-то неправильное, пожалуйста, исправить меня ..)

ответ

6

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

Класс DataContext работает как единое целое. Таким образом, вы создаете DataContext, вы создаете объекты, обновляете и удаляете объекты, вы отправляете все изменения, и после этого вы удаляете DataContext. Вы можете создать несколько классов DataContext для каждого запроса, по одной на (бизнес) транзакцию. Но в ASP.NET вы никогда не должны создавать DataContext, который переживает веб-запрос. Все DataContexts, созданные во время запроса, должны быть удалены, когда или раньше этот запрос завершен. Для этого есть две причины.

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

Вторая причина не кэширования DataContexts заключается в том, что они не являются потокобезопасными. Лучше всего видеть DataContext как единицу работы или транзакцию (бизнес). Вы создаете кучу новых объектов, добавляете их в DataContext, меняете некоторые другие, удаляете некоторые объекты, и когда вы закончите, вы вызываете SubmitChanges. Если другой запрос вызывает SubmitChanges на том же экземпляре во время этой операции, вы теряете идею транзакции. Когда вы позволяете коду делать это, в самой удачной ситуации ваши новые объекты будут сохранены, а ваша транзакция будет разделена на две отдельные транзакции. В худшем случае вы оставляете свой DataContext или объекты, которые он сохраняет в недопустимом состоянии, что может означать, что другие запросы терпят неудачу или недействительные данные поступают в вашу базу данных. И это не маловероятный сценарий, я видел, как странные вещи случаются в проектах, когда разработчики создали единый (статический) DataContext для каждого веб-сайта.

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

Важно знать, что представляет собой класс DataLayer. В вашем коде вы показываете нам только метод запроса. Нет методов CUD. Каждый метод означает одну транзакцию или вы хотите вызвать несколько методов и затем вызвать SaveChanges на DataLayer? Если вы хотите эту последнюю опцию, вам необходимо сохранить DataContext в качестве поля экземпляра, и в этом случае вы должны реализовать IDisposable на DataLayer.Когда каждый метод является собственной транзакцией, вы можете создать DataContext для каждого метода, и вы должны обернуть DataContext в оператор using. Однако обратите внимание, что удаление DataContext может вызвать проблемы при возврате объектов с ленивыми свойствами загрузки из метода. Эти свойства больше не могут быть загружены при размещении DataContext. Here - более интересная информация.

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

Я извиняюсь за мой длинный ответ :-)

+0

Нет, это был довольно крутой ответ. Я желаю, чтобы каждый дал ответ длинный и описательный. – Tarik

4

Вы никогда не хотите хранить DataContext class на уровне класса. Если вы это сделаете, вам придется реализовать IDisposable interface в своем классе и вызвать метод Dispose, когда вы знаете, что с ним все закончилось.

Лучше всего создать новый DataContext в вашем методе и использовать using statement, чтобы автоматически избавиться от него, когда вы закончите.

Даже если реализация IDisposable на DataContext не делает ничего, что является реализация детали, в то время как подвергая IDisposable интерфейс является контракт который вы всегда должны соблюдать.

Это особенно удобно, если вы перейти на LINQ-to-Entities и использовать ObjectContext class где необходимо вызов Dispose на экземпляре, когда вы сделали с ним, в противном случае, ресурсы не будут протекать до следующего сбора мусора.

+0

FYI: Я не был тем, кто проголосовал за ваш ответ. – Tarik

+1

@Braveyard: Не беспокойтесь, я знаю, что это были не вы. Во время downvote активность репутации @Hunter составляла -2 для этого вопроса. Поскольку у вопроса не было никаких отклонений, два ответа, и он не мог опускать свой собственный ответ, это был его голос. Но, как он сказал, это не имеет большого значения. Что такое один голос среди тысяч? Это вопрос предоставления правильной информации. – casperOne

1

Так что, кажется, единственное преимущество объявить об этом публично на весь класса является только номер один текст выше.

Да, объявление переменной уровня класса должно позволить всему классу получить доступ к одной и той же переменной. Его нельзя использовать, чтобы попытаться умышленно предотвратить сбор мусора. Модификатор доступа по свойствам, методам и т. Д. Используется для определения того, какие объекты, внешние или внутренние для вашего класса, могут получить доступ/модифицировать/обезьяну с помощью этого фрагмента кода.

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

+0

Время CG после того, как все будет завершено и отправлено клиенту? – Tarik

+1

@ Хранить потенциально или вообще не зависит от того, что еще содержит ссылку на этот объект. Как только запрос этой страницы будет завершен, вы можете предположить, что объекты, созданные в этом запросе, исчезли. – kemiller2002

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