В LINQ-SQL перенеситесь, DataContext является оператором использования - недостатки профессионалов

Может кто-то делать подачу по их мнению о профессионалах/недостатках между обертыванием DataContext в операторе использования или не в LINQ-SQL с точки зрения факторов как производительность, использование памяти, простота кодирования, правильного поступка и т.д.

Обновление: В одном конкретном приложении я испытал это, не перенося DataContext в использование блока, использование объема памяти продолжило увеличиваться, поскольку живые объекты не были выпущены для GC. Как в, в ниже примера, если я держу ссылку на Список объекта q и объекты доступа q, я создаю граф объектов, который не выпущен для GC.

DataContext с использованием

    using (DBDataContext db = new DBDataContext())
    {
        var q = 
            from x in db.Tables
            where x.Id == someId
            select x;

        return q.toList();
    }

DataContext, не используя и поддержанный

  DBDataContext db = new DBDataContext()
  var q = 
        from x in db.Tables
        where x.Id == someId
        select x;

    return q.toList(); 

Спасибо.

22
задан Jagd 3 October 2011 в 17:55
поделиться

5 ответов

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

DataContext создан как объект кратковременного использования, используйте его, выполните единицу работы, уйдите ... именно это вы и делаете с using.

Итак, преимущества:

  • Более быстрое закрытие соединений
  • Освобождение памяти от удаления (кэшированные объекты в содержимом)

Обратная сторона - больше кода? Но это не должно быть сдерживающим фактором, здесь вы правильно используете , используя .

Посмотрите здесь ответ Microsoft: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe

Краткая версия если вам нужно использовать , используя / .Dispose () :

Краткий ответ; нет, вам не обязательно, но вы должны ...

11
ответ дан 29 November 2019 в 05:31
поделиться

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

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

Я создал объект уровня данных как IDisposible. Когда он создается, создается DataContext (или, на самом деле, после первого вызова метода), а когда объект уровня данных удаляется, он закрывается и удаляет DataContext.

вот как это выглядит:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace PersonnelDL
{
    public class PersonnelData : IDisposable
    {
        #region DataContext management
        /// <summary>
        /// Create common datacontext for all data routines to the DB
        /// </summary>
        private PersonnelDBDataContext _data = null;
        private PersonnelDBDataContext Data
        {
            get
            {
                if (_data == null)
                {
                    _data = new PersonnelDBDataContext(ConfigurationManager.ConnectionStrings["PersonnelDB"].ToString());
                    _data.DeferredLoadingEnabled = false; // no lazy loading
                    //var dlo = new DataLoadOptions(); // dataload options go here
                }
                return _data;
            }
        }

        /// <summary>
        /// close out data context
        /// </summary>
        public void Dispose()
        {
            if (_data != null)
                _data.Dispose();
        }
        #endregion

        #region DL methods
        public Person GetPersonByID(string userid)
        {
            return Data.Persons.FirstOrDefault(p => p.UserID.ToUpper().Equals(userid.ToUpper()));
        }

        public List<Person> GetPersonsByIDlist(List<string> useridlist)
        {
            var ulist = useridlist.Select(u => u.ToUpper().Trim()).ToList();
            return Data.Persons.Where(p => ulist.Contains(p.UserID.ToUpper())).ToList();
        }

        // more methods...
        #endregion
    }
}
3
ответ дан 29 November 2019 в 05:31
поделиться

Ну, это IDisposable, так что, думаю, это неплохая идея. Люди из MSFT говорили, что они сделали DataContexts настолько легкими, насколько это возможно, чтобы вы могли создавать их с безрассудством, так что вы, вероятно, не много выиграете, хотя.....

5
ответ дан 29 November 2019 в 05:31
поделиться

В одном конкретном приложении я столкнулся с тем, что без обертывания DataContext в using блок, объем используемой памяти продолжал увеличиваться, так как живые объекты не освобождались для GC. Например, в следующем примере, если я держу ссылку на объект List

и обращаюсь к сущностям q, я создаю граф объектов, который не освобождается для GC.

DBDataContext db = new DBDataContext()
var qs = 
    from x in db.Tables
    where x.Id == someId
    select x;

return qs.toList();

foreach(q in qs)
{
    process(q);
    // cannot dispose datacontext here as the 2nd iteration 
    // will throw datacontext already disposed exception 
    // while accessing the entity of q in process() function
    //db.Dispose();
}

process(Table q)
{
    // access entity of q which uses deferred execution
    // if datacontext is already disposed, then datacontext 
    // already disposed exception is thrown
}

В этом примере я не могу утилизировать датаконтекст, потому что все экземпляры Table в переменной list qs **обмениваются одним и тем же датаконтекстом. После Dispose() обращение к сущности в process(Table q) вызывает исключение datacontext already disposed.

Уродливым ключом для меня было удаление всех ссылок на сущности для объектов q после цикла foreach. Лучшим способом, конечно, является использование оператора using.

Что касается моего опыта, я бы сказал, что лучше использовать оператор using.

1
ответ дан 29 November 2019 в 05:31
поделиться
  1. DataContext впервые получит объект из БД.
  2. В следующий раз, когда вы запустите запрос для получения того же объекта (с теми же параметрами): вы увидите запрос в профилировщике, но ваш объект в DataContext не будет заменен новым из БД !!

Не говоря уже о том, что за каждым DataContext стоит идентификационная карта всех объектов, которые вы запрашиваете из БД (вы не хотите, чтобы это было).

Вся идея DataContext - это Unit Of Work с Оптимистическим параллелизмом . Используйте его для короткой транзакции (только одна отправка) и удалите.

Лучший способ не забыть об утилизации - использовать ().

5
ответ дан 29 November 2019 в 05:31
поделиться
Другие вопросы по тегам:

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