Класс DataContext
63LINQ --- LINQ to DataSet и SQL --- Класс DataContext
»» В ДАННОЙ СТАТЬЕ ИСПОЛЬЗУЕТСЯ ИСХОДНЫЙ КОД ДЛЯ ПРИМЕРОВ
Класс DataContext обрабатывает подключение к базе данных. Он также обрабатывает запросы, обновления, вставки в базу данных, отслеживает идентичность, отслеживает изменения, обрабатывает их, обеспечивает целостность транзакций и даже создание базы данных. Класс DataContext транслирует запросы сущностных классов в операторы SQL, которые выполняются на подключенной базе данных.
Производный от DataContext класс [Your]DataContext предоставляет доступ к целой группе методов базы данных, таких как ExecuteQuery, ExecuteCommand и SubmitChanges. В дополнение к этим унаследованным методам класс [Your]DataContext будет содержать свойства типа System.Data.Linq.Table<T> для каждой таблицы и представления в базе данных, с которой будет использоваться LINQ to SQL, где каждый тип T — это сущностный класс, отображенный на конкретную таблицу или представление.
Например, взглянем на класс Northwind, который был сгенерирован инструментом SQLMetal. Это — класс [Your]DataContext для базы данных Northwind. Ниже приведена наиболее примечательная часть этого класса:
public partial class Northwind : System.Data.Linq.DataContext
{
static Northwind()
{ }
public Northwind(string connection) :
base(connection, mappingSource)
{
OnCreated();
}
public Northwind(System.Data.IDbConnection connection) :
base(connection, mappingSource)
{
OnCreated();
}
public Northwind(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
public Northwind(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
...
public System.Data.Linq.Table<Customer> Customers
{
get
{
return this.GetTable<Customer>();
}
}
...
Как видите, этот класс действительно наследуется от DataContext.
Легко заметить, что в нем объявлены пять конструкторов. Обратите внимание, что конструктор по умолчанию является приватным (private), поскольку для него не указан модификатор доступа, так что создать экземпляр [Your]DataContext без параметров не получится. Каждый из общедоступных конструкторов [Your]DataContext соответствует одному из конструкторов DataContext и вызывает эквивалентный конструктор класса DataContext в своем инициализаторе. В теле конструкторов вызывается только частичный метод OnCreated. Это позволяет разработчику реализовывать частичный метод OnCreated, который вызывается при каждом создании объекта [Your]DataContext.
Кроме того, в классе Northwind есть свойство по имени Customers типа Table<Customer>, где тип Customer представляет сущностный класс. Этот сущностный класс Customer отображается на таблицу Customers базы данных Northwind.
На самом деле не обязательно писать код, использующий класс [Your]DataContext. Вполне можно работать и со стандартным классом DataContext. Однако применение класса [Your]DataContext делает написание остального кода более удобным. Например, если вы используете класс [Your]DataContext, то каждая таблица представлена свойством, которое доступно непосредственно через объект [Your]DataContext. Пример показан ниже:
// Используйте свое подключение
Northwind db = new Northwind(
@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;Initial Catalog=C:\NORTHWIND.MDF;Integrated Security=True");
IQueryable<Customer> query = from c in db.Customers
where c.Country == "USA"
select c;
foreach (Customer cust in query)
{
Console.WriteLine(cust.CompanyName);
}
В предыдущем коде, поскольку осуществляется подключение с использованием класса [Your]DataContext по имени Northwind, есть возможность обращаться к таблице заказчиков Table<Customer> как к свойству Customers класса [Your]DataContext. Вот результат работы этого кода:
Если бы вместо этого подключение производилось с применением самого класса DataContext, нужно было бы использовать метод GetTable<T> объекта DataContext как показано в примере ниже:
DataContext dc = new Northwind(
@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;Initial Catalog=C:\NORTHWIND.MDF;Integrated Security=True");
IQueryable<Customer> query = from c in dc.GetTable<Customer>()
where c.Country == "USA"
select c;
foreach (Customer cust in query)
{
Console.WriteLine(cust.CompanyName);
}
Этот код дает тот же самый результат.
Так что использование класса [Your]DataContext просто удобнее, и это стоит взять на вооружение.
Класс DataContext реализует интерфейс IDisposable
Класс DataContext реализует интерфейс IDisposable и потому должен трактоваться правильно как освобождаемый (disposabe) объект. Это значит, что если создается новый класс, содержащий внутри себя класс DataContext или [Your]DataContext, что означает отношение "имеет" (has-a) между новым классом и классом DataContext или [Your]DataContext, то новый класс также должен реализовывать интерфейс IDisposable. Вопросы проектирования классов для правильной реализации интерфейса IDisposable выходят за рамки контекста настоящей статьи, но есть множество онлайновых ресурсов, посвященных этой теме.
Другое преимущество реализации интерфейса IDisposable классом DataContext состоит в том, что теперь можно применять оператор using для управления объектом DataContext или [Your]DataContext.