====== Использование контекстного класса ====== Под контекстным классом понимается класс, сгенерированный механизмом сборки в LINQ-to-SQL. Этот класс наследуется от //DataContext//. Имя класса может быть задано на [[developer:linq:db_mapping|уровне сайта или контента]], в случае отсутствия используется имя класса по умолчанию - //QPDataContext//. ===== Экземпляр по умолчанию ===== Если требуется работать только с одним контекстным классом, то можно использовать экземпляр контекстного класса по умолчанию, доступный как **LinqHelper.Context**. Он создается при первом запросе к нему и в случае вызова в Web-среде сохраняется на время выполнения текущего Web-запроса. В случае не-Web-приложений экземпляр сохраняется в статическом свойстве класса LinqHelper на все время жизни приложения. При создании независимого от БД кода следует иметь в виду, что экземпляр контекстного класса, доступный как **LinqHelper.Context** по умолчанию использует настройки с которыми он был сгенерирован. Сменить эти настройки можно до первого обращения к **LinqHelper.Context** через изменение статических свойств контекстного класса. Cуществует возможность использования нескольких экземпляров по умолчанию в Web-среде одновременно (если они находятся в разных пространствах имен). Единственное требование: чтобы имена сайтов, с которыми они работают, различались. ===== Явное инстанцирование контекстного класса ===== В случае, когда необходимо работать с несколькими контекстными классами можно использовать явный вызов конструктора, но если контекстный класс получены в режиме генерации кода, независимого от БД, то нужно использовать один из статических методов создания: static QPDataContext Create(string connection, string siteName, MappingSource mappingSource) static QPDataContext Create(string siteName, MappingSource mappingSource) static QPDataContext Create(string connection, string siteName) static QPDataContext Create(string connection) static QPDataContext Create() *//connection// -- строка подключения к БД *//siteName// -- имя сайта (в одной БД может быть несколько сайтов) *//mappingSource// -- источник данных для отображения на основе .map-файла, полученного в результате сборки контентов в LINQ-to-SQL классы Если какой либо из параметров не задан, то вместо него используются соответствующие статические свойства контекстного класса, которые можно изменить перед вызовом метода создания. ==== Особенности использования ==== В обычном сценарии использования LINQ-to-SQL классов, сушностные классы используют экземпляр контекстного по умолчанию (**LinqHelper.DataContext**) в тех случаях, когда им требуется внутри себя подгрузить какие-то данные, например для реализации M2M-полей. Но в случае явного инстанцирования контекстного класса, это не будет работать, так как внешний и внутренний контексты будут отличаться. Поэтому у каждого экземпляра сущностного класса теперь есть свойство **InternalDataContext**, которое позволяет явно задать внутренний контекст для таких операций. По умолчанию оно инициализируется значением **LinqHelper.DataContext**. Необходимость задавать внутренний контекст возникает при явном инстанцировании контекстного класса и использовании следующих операций: - Добавление новых статей. При этом экземпляр контекстного класса можно передавать прямо в конструкторе сущностного класса. Важно задать контекст до сохранения статьи. - Все операции с M2M-полями (свойствами-коллекциями внутри сущностных классов). Контекст необходимо задать у экземпляра сущностного класса перед обращением к его M2M-полю. - Использование [[developer:linq:image|дополнительных свойств полей-изображений]]. Контекст необходимо задать у экземпляра сущностного класса перед обращением к дополнительному полю. EventsArticle event = new EventsArticle(context); var item = ctx.TestArticles.Where(n => n.Id == 3737).Single(); var newCat = ctx.TestCategoryArticles.Where(n => n.Id == 1856).Single(); item.InternalDataContext = ctx; item.Categories.Add(newCat); ctx.SubmitChanges(); Если необходимо применение контекста сразу для коллекции объектов, то возможно использование метода, расширяющего IEnumerable: **ApplyContext(DataContext context)**, определенного для каждого сущностного класса. foreach (var item in ctx.PhotosArticles.Where(n => n.Photo != null).ApplyContext(ctx)) { // use item.PhotoUrl; } ===== Использование XmlMappingSource ===== Источник данных для отображения обычно получают с помощью статического метода [[http://msdn.microsoft.com/ru-ru/library/system.data.linq.mapping.xmlmappingsource.fromxml.aspx|XmlMappingSource.FromXml]], в который передается строка с XML-содержимым отображения. Само XML-содержимое можно получить с помощью одного из экземплярных методов класса DBConnector: * [[api:dbconnector:mapping#GetMapFileContents|GetMapFileContents]] * [[api:dbconnector:mapping#GetDefaultMapFileContents|GetDefaultMapFileContents]] Пример: XmlMappingSource map = XmlMappingSource.FromXml(Cnn.GetDefaultMapFileContents(Cnn.GetSiteId("Sandbox Net"))); XmlMappingSource map2 = XmlMappingSource.FromXml(Cnn.GetMapFileContents(Cnn.GetSiteId("Sandbox Net"), "EventsDataContext.map")); ===== Cтатические свойства контекстного класса ===== Позволяют настроить значения по умолчанию, которые потом будут использованы при инстанцировании контекстных классов, в том числе и для **LinqHelper.Context** перед первым обращением к нему. ***DefaultConnectionString** -- строка подключения к БД. Инициализируется строкой из секции //connectionStrings// файла //web.config//, название которой задано на [[developer:linq:db_mapping|уровне сайта]]. Если название не задано, то используется название по умолчанию - //qp_database//. ***DefaultSiteName** -- имя сайта. Инициализируется именем сайта, для которого были сгенерированы LINQ-to-SQL классы. ***DefaultXmlMappingSource** -- Инициализируется вызовом //XmlMappingSource.FromXml(Cnn.GetDefaultMapFileContents(Cnn.GetSiteId("имя сайта")))//. В качестве имени указывается имя сайта, для которого были сгенерированы LINQ-to-SQL классы. Пример изменения статических свойств: QPDataContext.DefaultXmlMappingSource = XmlMappingSource.FromXml(Cnn.GetDefaultMapFileContents(Cnn.GetSiteId("Sandbox Net 7"))); QPDataContext.DefaultSiteName = "Sandbox Net 7";