Linq - чудесная технология, суть которой заключается в манипулировании данными посредством Sql-подобного языка запросов. Для работы с базами данных используется так называемый
Linq2Sql - это всё тот же
Linq, но ориентированный на базы данных.
В этой статье мы попытаемся применить
LINQ для работы с базой данных на
Access. Почему Access? Просто
LINQ по умолчанию поддерживает работу только с MS Server, чтобы заставить его работать с другими субд, надо немного попотеть.
Что ж, приступим...
Для начала я создал простецкую бд с двумя таблицами: Сотрудник и Должность. Соответственно, каждый сотрудник имеет свою фамилию, имя, отчество и должность, которая оценивается в денежном эквиваленте. Такая база данных создана только в качестве примера, дабы было на чём тренироваться при работе с
Linq.
Как я уже говорил, Linq не предназначен для работы с Access. Чтобы заставить его работать с этой субд можно воспользоваться библиотекой Alinq, которую можно скачать по ссылке: http://www.alinq.org/download/ALinq_V2.6.2.msi
После установки, все необходимые файлы у меня разместились в C://ProgramFiles(x86)/alinq
Мы ещё будем обращаться к этому каталогу в ходе реализации приложения.
Итак, начнём создавать наше приложение. Надеюсь, вы сами сможете создать новый проект.
Далее нам необходимо подключить необходимые библиотеки для работы с Linq To Access. В Solution Explorer'e вызовем контекстное меню и выберем Add Reference. Далее на вкладке Browse перейдём в каталог, куда установился Alinq и добавим 2 библиотеки: Alinq.Access.dll и Alinq.dll
В главной форме добавим ссылки на сборки:
using ALinq.Access;
using ALinq;
Далее нам нужно создать классы, которые соответствуют таблице в бд. Класс Worker имеет следующий вид:
using System;
using System.Collections.Generic;
using System.Text;
using ALinq.Mapping;
namespace LinqAccess1
{
[Table(Name="Сотрудник")]
public class Worker
{
[Column(Name="Код",IsDbGenerated=true, IsPrimaryKey=true)]
public int ID{get;set;}
[Column(Name="Фамилия")]
public string FirstName{get;set;}
[Column(Name="Имя")]
public string Name{get;set;}
[Column(Name="Отчество")]
public string SecondName{get;set;}
[Column(Name="Должность")]
public int WorkType{get;set;}
}
}
Немного поясню представленный код. В квадратных скобках указываются атрибуты свойств. Именно таким образом Linq может понять что класс Worker - это сущность, которая соответствует таблице Сотрудник. У таблицы есть поля, которые представлены полями в классе. Опять же, данные поля описаны соответствующими атрибутами, так например поле
Код таблицы бд, представлено в классе полем:
[Column(Name="Код",IsDbGenerated=true, IsPrimaryKey=true)]
public int ID{get;set;};
Где в кв. скобках сказано (если переводить на вольный русский язык), что это поле соответствует полю "Код" в бд, это поле является первичным ключом.
Так как у нас в бд две таблицы, то необходимо создать ещё один класс - WorkTypes, который будет отвечать за таблицу Должность.
using System;
using System.Collections.Generic;
using System.Text;
using ALinq.Mapping;
namespace LinqAccess1
{
[Table(Name="Должность")]
public class WorkTypes
{
[Column(Name = "Код", IsPrimaryKey = true, IsDbGenerated = true)]
public int ID { get; set; }
[Column(Name = "Должность")]
public string WorkTypeName { get; set; }
[Column(Name = "Зарплата")]
public int Zarplata { get; set; }
}
}
После реализации соответствующих сущностей, попробуем отобразить содержимое этих таблиц. Кинем на форму dataGridView. Объявим глобальную переменную типа DataContext. Этот тип по отвечает за соединение с бд и за представление данных, находящихся в таблицах.
public partial class Form1 : Form
{
Table<Worker> workers;
DataContext context;
public Form1()
{
InitializeComponent();
context = new DataContext(@"db1.mdb");
workers = context.GetTable<Worker>();
dataGridView1.DataSource = workers;
}
Здесь в конструкторе формы мы инициализируем переменную context, где в параметрах конструктора передаём путь до нашей базы данных. Далее мы получаем содержимое таблицы Сотрудник, и отображаем данные в гриде.
В гриде у нас отображается информация из таблицы Сотрудник, при этом мы не написали ни единого Sql-запроса. В столбце WorkType у нас находятся внешние ключи, эти двоечки, единички совершенно не радуют глаз, т.к не дают пользователю совершенно никакой информации о том, на какой должности работает сотрудник (откуда он может знать, что цифра 4 соответствует программисту..). Дабы решить эту проблему составим linq-запрос и повесим его на кнопку:
private void button1_Click(object sender, EventArgs e)
{
IQueryable query=from person in workers join worktype in context.GetTable<WorkTypes>()
on person.WorkType equals worktype.ID select new {FirstN=person.FirstName,Name=person.Name,Second=
person.SecondName,Worktype=worktype.WorkTypeName};
dataGridView1.DataSource = query;
}
Теперь в столбце WorkType отображается соответствующая должность, которую занимает сотрудник.
Пойдём ещё дальше, и составим запрос на выборку сотрудников, у которых з/п >= значению в textBox'e
IQueryable q = from worker in workers
join worktype in context.GetTable<WorkTypes>() on
worker.WorkType equals worktype.ID
where worktype.Zarplata >= int.Parse(textBox1.Text)
select new
{
FirstName = worker.FirstName,
Name = worker.Name,
Worktype = worktype.WorkTypeName,
zarpl = worktype.Zarplata
};
dataGridView1.DataSource = q;
В целом, тестовый пример готов. Наверняка у вас возникли сложности в понимании linq запросов, для этого рекомендую вам книгу Д.Албахари Карманный справочник по Linq в C#. Данная книга позволит вам в краткие сроки постичь Linq.
Исходники: приложение не будет работать при не установленном Alinq!
http://dl.dropbox.com/u/16627362/LinqAccess1.rar
Автор:
Богданов М.
12.07.2012