Методы GetCommand(), GetTable() и GetChangeSet()

50

»» В ДАННОЙ СТАТЬЕ ИСПОЛЬЗУЕТСЯ ИСХОДНЫЙ КОД ДЛЯ ПРИМЕРОВ

GetCommand()

Еще один потенциально полезный метод — это GetCommand. Когда вызывается метод GetCommand на объекте DataContext и ему передается интерфейс LINQ to SQL по имени IQueryable, то возвращается объект типа System.Data.Common.DbCommand. Возвращенный объект DbCommand содержит доступ к нескольким ключевым компонентам, которые будут использованы запросом.

Извлекая объект DbCommand с помощью метода GetCommand, можно получить ссылку на объекты CommandText, CommandTimeout, Connection, Parameters и Transaction, наряду с некоторыми другими, относящимися к переданному запросу. Это позволяет не только просматривать эти объекты, но и модифицировать их, изменяя значения по умолчанию, без модификации одних и тех же запросов, которые будут выполнены текущим экземпляром DataContext.

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

Метод GetCommand имеет один прототип, описанный ниже:

System.Data.Common.DbCommand GetCommand(IQueryable query)

Этому методу передается запрос LINQ to SQL в форме IQueryable, а возвращает он System.Data.Common.DbCommand этого запроса.

В следующем примере получается объект DbCommand для изменения значения CommandTimeout запроса. На консоль выводится значение CommandText, которым будет сам запрос SQL:

// Используйте свое подключение
            Northwind db = new Northwind(@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;
                       Initial Catalog=C:\NORTHWIND.MDF;
                       Integrated Security=True");

            IQueryable<Customer> custs = from c in db.Customers
                                         where c.Region == "WA"
                                         select c;

            System.Data.Common.DbCommand dbc = db.GetCommand(custs);
            Console.WriteLine("Таймаут запроса: {0}\n",dbc.CommandTimeout);

            dbc.CommandTimeout = 1;

            Console.WriteLine("SQL-код запроса: \n{0}\n",dbc.CommandText);
            Console.WriteLine("Таймаут запроса: {0}\n", dbc.CommandTimeout);

            foreach (Customer c in custs)
            {
                Console.WriteLine(c.CompanyName);
            }

Об этом примере говорить особо нечего. Здесь просто объявляется запрос, который передается методу GetCommand. Затем отображается значение CommandTimeout для возвращенного объекта DbCommand. Далее значение CommandTimeout устанавливается в 1 и выводится сам запрос SQL вместе с новым значением CommandTimeout. И последнее — выполняется перечисление результатов, возвращенных запросом. Ниже показаны результаты запуска этого кода:

Пример вызова метода GetCommand

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

GetChangeSet()

Иногда удобно иметь возможность получить список всех сущностных объектов, которые будут вставлены, изменены или удалены при вызове метода SubmitChanges. Метод GetChangeSet служит именно для этого.

Метод GetChangeSet имеет один прототип, описанный ниже:

ChangeSet GetChangeSet()

Этот метод не принимает ничего и возвращает объект ChangeSet. Объект ChangeSet содержит коллекции типа IList<T> для вставленных, модифицированных и удаленных объектов, где T — сущностный класс. Эти свойства-коллекции называются Inserts, Updates и Deletes соответственно.

Затем можно выполнить перечисление каждой из этих коллекций для того, чтобы просмотреть содержащиеся в них объекты.

В следующем примере сущностный объект модифицируется, вставляется и удаляется. Затем с помощью метода GetChangeSet извлекается ChangeSet и производится перечисление каждой коллекции:

// Используйте свое подключение
            Northwind db = new Northwind(@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;
                       Initial Catalog=C:\NORTHWIND.MDF;
                       Integrated Security=True");

            Customer cust = (from c in db.Customers
                             where c.CustomerID == "LAZYK"
                             select c).Single<Customer>();
            cust.Region = "Washington";

            db.Customers.InsertOnSubmit(
              new Customer
              {
                  CustomerID = "LAWN",
                  CompanyName = "Lawn Wranglers",
                  ContactName = "Mr. Abe Henry",
                  ContactTitle = "Owner",
                  Address = "1017 Maple Leaf Way",
                  City = "Ft. Worth",
                  Region = "TX",
                  PostalCode = "76104",
                  Country = "USA",
                  Phone = "(800) MOW-LAWN",
                  Fax = "(800) MOW-LAWO"
              });

            Customer cust2 = (from c in db.Customers
                              where c.CustomerID == "LONEP"
                              select c).Single<Customer>();
            db.Customers.DeleteOnSubmit(cust2);
            cust2 = null;

            ChangeSet changeSet = db.GetChangeSet();

            Console.WriteLine("\nДобавленные сущности: ");
            foreach (Customer c in changeSet.Inserts)
            {
                Console.WriteLine("Заказчик {0} будет добавлен.", c.CompanyName);
            }

            Console.WriteLine("\nМодифицированные сущности: ");
            foreach (Customer c in changeSet.Updates)
            {
                Console.WriteLine("Заказчик {0} будет обновлен", c.CompanyName);
            }

            Console.WriteLine("\nУдаление сущности: ");
            foreach (Customer c in changeSet.Deletes)
            {
                Console.WriteLine("Заказчик {0} будет удален.", c.CompanyName);
            }

В этом примере сначала модифицируется Region заказчика LAZYK. Затем заказчик LAWN вставляется, а заказчик LONEP удаляется. После этого с помощью метода GetChangeSet получается ChangeSet. И, наконец, осуществляется перечисление каждой коллекции — Inserts, Updates и Deletes — с отображением каждого сущностного объекта в соответствующей коллекции.

Ниже показаны результаты:

Пример вызова метода GetChangeSet

Конечно, в предыдущем примере можно выполнять перечисление каждой коллекции, предполагая, что каждый элемент является объектом Customer, потому что известно, что так оно и есть. Однако во многих случаях в коллекции может существовать более одного типа объектов, и делать такие предположения не получится. В таких ситуациях понадобится написать собственное перечисление для обработки множественных типов данных. Помочь в этом может операция OfType.

GetTable()

Метод GetTable используется для получения ссылки на последовательность Table из DataContext для определенной таблицы базы данных. Этот метод обычно применяется только вместе с классом DataContext, а не [Your]DataContext. Использование класса [Your]DataContext является предпочтительной техникой, поскольку этот класс уже будет иметь свойство-последовательность Table, ссылающееся на каждую отображенную таблицу.

Метод GetTable имеет два прототипа, которые описаны ниже:

Первый прототип GetTable
Table<T> GetTable<T>()

Этому методу предоставляется указанный отображаемый сущностный тип Т, и он возвращает последовательность Table объектов типа Т.

Второй прототип GetTable
ITable GetTable(Type type)

Этот метод принимает Type сущностного объекта и возвращает интерфейс таблицы. Затем этот интерфейс ITable можно использовать по своему усмотрению. Чтобы применять интерфейс ITable, как если бы это была таблица, не забудьте привести его к IQueryable<T>.

В примере первого прототипа ниже для извлечения определенного заказчика используется стандартный класс DataContext вместо класса [Your]DataContext по имени Northwind:

// Используйте свое подключение
            Northwind db = new Northwind(@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;
                       Initial Catalog=C:\NORTHWIND.MDF;
                       Integrated Security=True");

            DataContext dx = new DataContext(@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;
                       Initial Catalog=C:\NORTHWIND.MDF;
                       Integrated Security=True");

            Customer cust = (from c in dx.GetTable<Customer>()
                             where c.CustomerID == "LAZYK"
                             select c).Single<Customer>();

            Console.WriteLine("\n  Заказчик {0} извлечен.", cust.CompanyName);

Здесь вызывается метод GetTable для получения ссылки на таблицу Customer, чтобы иметь возможность извлечь конкретного заказчика. Вот результат:

Пример вызова первого прототипа GetTable

Для примера второго прототипа метода GetTable используется DataContext вместо [Your]DataContext. Ниже представлен тот же базовый пример, что и предыдущий, но в нем применяется второй прототип:

// Используйте свое подключение
            Northwind db = new Northwind(@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;
                       Initial Catalog=C:\NORTHWIND.MDF;
                       Integrated Security=True");

            DataContext dx = new DataContext(@"Data Source=MICROSOF-1EA29E\SQLEXPRESS;
                       Initial Catalog=C:\NORTHWIND.MDF;
                       Integrated Security=True");

            Customer cust = (from c in ((IQueryable<Customer>)dx.GetTable(typeof(Customer)))
                             where c.CustomerID == "LAZYK"
                             select c).Single<Customer>();

            Console.WriteLine("\n  Заказчик {0} извлечен.", cust.CompanyName);

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

Пройди тесты
Лучший чат для C# программистов