1. Темы лекции: Entity Framework.
Практическое задание: Entity Framework.
Тренер: Игорь Шкулипа, к.т.н.
Разработка Веб-приложений на платформе
Microsoft .NET Framework.
Занятие 4
2. http://www.slideshare.net/IgorShkulipa 2
ORM
ORM (англ. Object-relational mapping, рус. Объектно-реляционное
отображение) — технология программирования, которая связывает
базы данных с концепциями объектно-ориентированных языков
программирования, создавая «виртуальную объектную базу данных».
Суть проблемы, которая решается с помощью ORM-слоя, заключается в
необходимости преобразования объектных структур в памяти
приложения в форму, удобную для сохранения в реляционных базах
данных, а также для решения обратной задачи — развертывания
реляционной модели в объектную, с сохранением свойств объектов и
отношений между ними.
Entity Framework представляет специальную объектно-
ориентированную технологию на базе .NET для работы с данными.
Если традиционные средства ADO.NET позволяют создавать
подключения, команды и прочие объекты для взаимодействия с
базами данных, то EF представляет собой более высокий уровень
абстракции, который позволяет абстрагироваться от самой базы
данных и работать с данными независимо от типа хранилища. если на
физическом уровне мы оперируем таблицами, индексами, первичными
и внешними ключами, но на концептуальном уровне, который нам
предлагает EF, мы уже работаем с объектами.
3. http://www.slideshare.net/IgorShkulipa 3
Entity Framework
Центральной концепцией Entity Framework является понятие сущности
или entity. Сущность представляет набор данных, ассоциированных с
определенным объектом. Поэтому данная технология предполагает
работу не с таблицами, а с объектами и их наборами.
Любая сущность, как и любой объект из реального мира, обладает рядом
свойств. Свойства не обязательно представляют простые данные типа
int, но и могут представлять более комплексные структуры данных. И
у каждой сущности может быть одно или несколько свойств, которые
будут отличать эту сущность от других и будут уникально определять
эту сущность. Подобные свойства называют ключами.
При этом сущности могут быть связаны ассоциативной связью один-ко-
многим, один-ко-одному и многие-ко-многим, подобно тому, как в
реальной базе данных происходит связь через внешние ключи.
Отличительной чертой Entity Framework является использование
запросов LINQ для выборки данных из БД. С помощью LINQ мы
можем не только извлекать определенные строки, хранящие объекты,
из БД, но и получать объекты, связанные различными ассоциативными
связями.
4. http://www.slideshare.net/IgorShkulipa 4
Entity Data Model
Другим ключевым понятием является Entity Data Model. Эта модель
сопоставляет классы сущностей с реальными таблицами в БД.
Entity Data Model состоит из трех уровней: концептуального, уровень
хранилища и уровень сопоставления (маппинга).
• На концептуальном уровне происходит определение классов
сущностей, используемых в приложении.
• Уровень хранилища определяет таблицы, столбцы, отношения
между таблицами и типы данных, с которыми сопоставляется
используемая база данных.
• Уровень сопоставления (маппинга) служит посредником между
предыдущими двумя, определяя сопоставление между свойствами
класса сущности и столбцами таблиц.
Таким образом, мы можем через классы, определенные в приложении,
взаимодействовать с таблицами из базы данных.
5. http://www.slideshare.net/IgorShkulipa 5
Способы взаимодействия с БД
Entity Framework предполагает три возможных способа взаимодействия с
базой данных:
• Database first: Entity Framework создает набор классов,
которые отражают модель конкретной базы данных
• Model first: сначала разработчик создает модель базы данных,
по которой затем Entity Framework создает реальную базу данных
на сервере.
• Code first: разработчик создает класс модели данных, которые
будут храниться в БД, а затем Entity Framework по этой модели
генерирует базу данных и ее таблицы
6. http://www.slideshare.net/IgorShkulipa 6
Создание запросов
Чтобы эффективно работать с Entity Framework нужно в первую очередь
знать, как выполнять запросы к хранилищу данных с использованием
EF. Хотя к счастью в Entity Framework создавать запросы очень легко,
так как в основном для этого применяются методы LINQ, которые
напоминают SQL-выражения.
Вначале производится общий запрос к хранилищу данных. Затем
свойство объекта представляет объект-коллекцию DbSet и возвращает
объект IEnumerable<T>. То есть мы можем получить все объекты из
таблицы, например, следующим образом:
IEnumerable<SomeTable> someTable = tableContainer.SomeTable;
foreach(var st in someTable )
{
Console.WriteLine(st.Name);
}
17. http://www.slideshare.net/IgorShkulipa 17
Code-First к существующей базе данных
Данный подход также представляет способ взаимодействия Code First,
однако база данных не генерируется автоматически, а создается
самим разработчиком. Иногда программисты называют данный подход
Code Second. Данный подход удобен, когда у нас уже есть база
данных.
19. http://www.slideshare.net/IgorShkulipa 19
Database First
Database First был первым подходом, который появился в Entity
Framework. Данный подход во многом похож на Model First и подходит
для тех случаев, когда разработчик уже имеет готовую базу данных.
Чтобы Entity Framework мог получить доступ к базе данных, в системе
должен быть установлен соответствующий провайдер. Так, Visual
Studio уже поддерживает соответствующую инфраструктуру для СУБД
MS SQL Server. Для остальных СУБД, например, MySQL, Oracle и
других надо устанавливать соответствующие провайдеры.
26. http://www.slideshare.net/IgorShkulipa 26
Строка подключения
Иногда может потребоваться динамически изменять местоположение или
название базы данных, к которой идет подключения. В этом случае
нам надо указать стрку подключения. По умолчанию Visual Studio
добавляет в проекты файл конфигурации. В проектах для десктопных
приложений этот файл называется App.config, в проектах веб-
приложений это файл Web.config. Но вне зависимости от типа проекта
файл конфигурации имеет определенную структуру и элементы, среди
которых также есть также элемент connectionStrings, определяющий
строки подключения.
27. http://www.slideshare.net/IgorShkulipa 27
Навигационные свойства
public partial class Person
{
public Person()
{
this.Team = new HashSet<Team>();
}
public int PID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Middle { get; set; }
public System.DateTime Birthday { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
//Навигационные свойства задают связи между таблицами
public virtual Position Position { get; set; }
public virtual ICollection<Team> Team { get; set; }
}
28. http://www.slideshare.net/IgorShkulipa 28
Связь один ко многим
public partial class Person
{
public Person()
{
this.Team = new HashSet<Team>();
}
public int PID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Middle { get; set; }
public System.DateTime Birthday { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public virtual Position Position { get; set; }
public virtual ICollection<Team> Team { get; set; }
}
public partial class Position
{
public Position()
{
this.Person = new HashSet<Person>();
}
public int POSID { get; set; }
public string PName { get; set; }
public virtual ICollection<Person> Person { get; set; }
}
29. http://www.slideshare.net/IgorShkulipa 29
Связь многие ко многим
public partial class Person
{
public Person()
{
this.Team = new HashSet<Team>();
}
public int PID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Middle { get; set; }
public System.DateTime Birthday { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public virtual Position Position { get; set; }
public virtual ICollection<Team> Team { get; set; }
}
public partial class Team
{
public Team()
{
this.Person = new HashSet<Person>();
}
public int TID { get; set; }
public string TName { get; set; }
public virtual ICollection<Person> Person { get; set; }
}
30. http://www.slideshare.net/IgorShkulipa 30
Основные операции с данными
Большинство операций с данными представляют собой CRUD-операции
(Create, Read, Update, Delete), то есть получение данных, создание,
обновление и удаление. Entity Framework позволяет легко производить
данные операции.
31. http://www.slideshare.net/IgorShkulipa 31
Паттерн «Репозиторий»
Одним из наиболее часто используемых паттернов при работе с данными
является паттерн Репозиторий.
Репозиторий позволяет абстрагироваться от конкретных подключений к
источникам данных, с которыми работает программа, и является
промежуточным звеном между классами, непосредственно
взаимодействующими с данными, и остальной программой.
32. http://www.slideshare.net/IgorShkulipa 32
Пример см. Занятие №3. Интерфейс
public interface IRepository<T>
{
void Insert(T entity);
void Delete(T entity);
void Update(T entity, T newValue);
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
IQueryable<T> SelectAll();
void SubmitAll();
}
33. http://www.slideshare.net/IgorShkulipa 33
Реализация
public class Repository<T> : IRepository<T> where T : class {
protected DbContext DBContext;
public Repository(DbContext dataContext) {
DBContext = dataContext;
}
public void Insert(T entity) {
DBContext.Set<T>().Add(entity);
}
public void Delete(T entity) {
DBContext.Set<T>().Remove(entity);
}
public void Update(T entity, T newValue) {
var entry = DBContext.Entry<T>(entity);
entry.CurrentValues.SetValues(newValue);
entry.State = EntityState.Modified;
}
public IQueryable<T> Find(Expression<Func<T, bool>> predicate) {
return DBContext.Set<T>().Where(predicate);
}
public IQueryable<T> SelectAll() {
return DBContext.Set<T>();
}
public void SubmitAll() {
DBContext.SaveChanges();
}
}
34. http://www.slideshare.net/IgorShkulipa 34
Модифицированный контракт
[DataContract(Namespace = "WCFS1")]
public class Contact
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Middle { get; set; }
[DataMember]
public string Surname { get; set; }
[DataMember]
public DateTime Birthday { get; set; }
[DataMember]
public string Address { get; set; }
[DataMember]
public string Phone { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string Position { get; set; }
[DataMember]
public List<string> Teams { get; set; }
}
35. http://www.slideshare.net/IgorShkulipa 35
Служба
public class Service1 : IService1
{
IRepository<Person> persons;
IRepository<Position> positions;
IRepository<Team> teams;
Model1Container model;
public Service1(){
model = new Model1Container();
persons = new Repository<Person>(model);
positions = new Repository<Position>(model);
teams = new Repository<Team>(model);
}
public List<string> GetNames(){
var p = persons.SelectAll();
var res = from pe in p.ToArray<Person>()
where true
select pe.Name;
return res.ToList<string>();
}
public Contact GetData(string name){
Contact res = new Contact();
var pers = from p in persons.SelectAll()
where p.Name == name
select p;
res.Name=pers.ToArray<Person>()[0].Name;
...
return res;
}
36. http://www.slideshare.net/IgorShkulipa 36
Модификация на клиенте.
public class ContactViewModel: INotifyPropertyChanged
{
...
public string DetailsText
{
get
{
string result= CurrentContact.Name + "n" +
CurrentContact.Middle + "n" +
CurrentContact.Surname + "n" +
CurrentContact.Birthday.ToString() + "n" +
CurrentContact.Address + "n" +
CurrentContact.Phone + "n" +
CurrentContact.Email + "n"+
CurrentContact.Position+"n";
if (CurrentContact.Teams!=null)
foreach (string t in CurrentContact.Teams)
{
result += t + "n";
}
return result;
}
}
}