Скачать презентацию Entity Framework ВВЕДЕНИЕ В EF Пример Скачать презентацию Entity Framework ВВЕДЕНИЕ В EF Пример

Entity Framework.pptx

  • Количество слайдов: 35

Entity Framework Entity Framework

ВВЕДЕНИЕ В EF ВВЕДЕНИЕ В EF

Пример базы Пример базы

Модель [Table( Модель [Table("Customer", Schema = "Sales. LT")] public class Customer { public Customer() { this. Customer. Adresses = new Hash. Set(); } public int Customer. ID { get; protected set; } public string First. Name { get; set; } public string Last. Name { get; set; } public Name. Style { get; set; } //. . . public virtual ISet Customer. Adresses { get; protected set; } [Table("Customer. Address", Schema = "Sales. LT")] public class Customer. Address { [Key, Foreign. Key("Address"), Column(Order = 1)] public int Address. ID { get; protected set; } [Key, Foreign. Key("Customer"), Column(Order = 0)] public int Customer. ID { get; protected set; } public string Address. Type { get; set; } public virtual Address { get; set; } public virtual Customer { get; set; } } } [Table("Address", Schema = "Sales. LT")] public class Address { public Address() { this. Customer. Adresses = new Hash. Set(); } public int Address. ID { get; protected set; } public string Address. Line 1 { get; set; } public string City { get; set; } //. . . public virtual ISet Customer. Adresses { get; protected set; } } public class Adwenture. Works. Context : Db. Context { public Db. Set

Addresses { get; set; } public Db. Set Customers { get; set; } public Db. Set Customer. Addresses { get; set; } }

Пример использования using (var context = new Adwenture. Works. Context()) { var customers = Пример использования using (var context = new Adwenture. Works. Context()) { var customers = from customer in context. Customers let cust. Address = customer. Customer. Adresses from addr in cust. Address where addr. Address. City == "Ижевск" select new { customer. First. Name, customer. Last. Name }; customers. Take(10). To. List(). For. Each(c => Console. Write. Line("{0}, {1}", c. First. Name, c. Last. Name)); var new. Address = new Address { City = "Ижевск", Address. Line 1 = "К. Маркса 246", Country. Region = "Russia", Postal. Code = "426000", State. Province = "Udmurtia" }; context. Addresses. Add(new. Address); var new. Customer = new Customer { First. Name = "Mihail", Last. Name = "Romanov", Email. Address = "mihail_romanov@epam. com", }; new. Customer. Adresses. Add(new Customer. Address { Address. Type = "Work", Address = new. Address }); context. Customers. Add(new. Customer); context. Save. Changes(); }

Режимы EF • Database First • Model First • Code First Режимы EF • Database First • Model First • Code First

Элементы ORM • Маппинг – проекция структуры классов на структуру базы – обычно требуется: Элементы ORM • Маппинг – проекция структуры классов на структуру базы – обычно требуется: • проекция классов (иерархий) на таблицы • property на поля таблиц (в т. ч. ключи) • связи между классами на связи между таблицами • Механизм запросов • Механизм обновления + отслеживание измененных объектов

Иерархии типов и маппинг • Table per Hierarchy (TPH) • Table per Type (TPT) Иерархии типов и маппинг • Table per Hierarchy (TPH) • Table per Type (TPT) • Table per Concrete class (TPC)

Table per Hierarchy (TPH) Id 1 2 3 First. Name 1 First. Name 2 Table per Hierarchy (TPH) Id 1 2 3 First. Name 1 First. Name 2 First. Name 3 Last. Name 1 Last. Name 2 Last. Name 3 Position Organization Position Org 1 Discriminator Person Employee Contact. Person

Table per Type (TPT) Id 1 2 3 First. Name 1 First. Name 2 Table per Type (TPT) Id 1 2 3 First. Name 1 First. Name 2 First. Name 3 Last. Name 1 Last. Name 2 Last. Name 3 Id 2 Position Id 3 Organization Org 1

Table per Concrete class (TPC) Table per Concrete class (TPC)

МАППИНГ В EF МАППИНГ В EF

Механизмы описания маппинга в EF • Соглашения (Conventions) – например, все свойства с именем Механизмы описания маппинга в EF • Соглашения (Conventions) – например, все свойства с именем Id – первичные ключи – могут быть отключены (свои создавать пока нельзя) • Аннотации (Data Annotations) – использование атрибутов типа [Table()] • Fluent API – явное указание настроек маппинга

Соглашения (Conventions) public class Adwenture. Works. Context : Db. Context { public Db. Set<Customer> Соглашения (Conventions) public class Adwenture. Works. Context : Db. Context { public Db. Set Customers { get; set; } } • Рассматриваются все публичные свойства типа Db. Set в наследнике от Db. Context и производится маппинг для: – класса T – его предков и наследников – связанных типов • Типы проецируются по принципу table-perhierarhy

Соглашения (Conventions) 2 • Свойства переносятся на одноименные поля таблиц • Свойства с именем Соглашения (Conventions) 2 • Свойства переносятся на одноименные поля таблиц • Свойства с именем вида “ID”, “Id” или “{Имя класса}ID” являются первичным ключом – поле в базе объявлено как Identity • Поле, имеющее тип равный другой сущности или коллекции – является навигационным – поле внешнего ключа носит название {связанная сущность}Id

Data Annotations [Table( Data Annotations [Table("Customer", Schema = "Sales. LT")] public class Customer { public int Customer. ID { get; protected set; } [Required] public string First. Name { get; set; } [Required] public string Last. Name { get; set; } [Max. Length(200)] public string Email. Address { get; set; } } Атрибут Значение [Table] Маппинг сущности на таблицу [Key] Первичный ключ [Database. Generated] Способ генерации значения в базе: None, Identity, Generated [Foreign. Key] Свойство – внешний ключ [Required] Обязательное свойство [Not. Mapped] Свойство не мапится [Column] Маппинг свойства на колонку [Complex. Type] Сложный тип (не сущность) [Timestamp] Поля типа timestamp

Fluent API public class Adwenture. Works. Context : Db. Context { protected override void Fluent API public class Adwenture. Works. Context : Db. Context { protected override void On. Model. Creating(Db. Model. Builder model. Builder) { var customer = model. Builder. Entity(); customer. Has. Key(c => c. Customer. ID). To. Table("Customer", "Sales. LT"); customer. Property(c => c. First. Name). Is. Required(). Is. Unicode(); customer. Property(c => c. Last. Name). Is. Required(). Is. Unicode(); customer. Property(c => c. Email. Address). Is. Optional(). Has. Max. Length(200). Is. Unicode( false). Is. Variable. Length(); } } Метод Значение Entity<>() Маппинг сущности Complex. Type<>() Маппинг сложного типа Property() Маппинг свойства Map() Сложное описание маппинга Has. Key Описание ключа

ПОЛУЧЕНИЕ ОБЪЕКТОВ ПОЛУЧЕНИЕ ОБЪЕКТОВ

Запросы var customer. Id 1 = context. Customers. Find(1); var customers = from customer Запросы var customer. Id 1 = context. Customers. Find(1); var customers = from customer in context. Customers let cust. Address = customer. Customer. Adresses from addr in cust. Address where addr. Address. City == "Ижевск" select new { customer. First. Name, customer. Last. Name }; var customers 1 = context. Set();

Загрузка связанных сущностей • По умолчанию загружаются только сами сущности, но не связанные! • Загрузка связанных сущностей • По умолчанию загружаются только сами сущности, но не связанные! • Стратегии загрузки в EF – Ленивая – Жадная – Явная (по требованию)

Ленивая загрузка (Lazily Loading) var customer. Id 1 = context. Customers. Find(1); var adresses Ленивая загрузка (Lazily Loading) var customer. Id 1 = context. Customers. Find(1); var adresses = customer. Id 1. Customer. Adresses; • Требования – класс должен быть объявлен как • public • не sealed и не abstract • с публичным или защищенным конструктором – навигационное свойство должно быть • virtual • иметь public getter

Жадная загрузка (Eagerly Loading) var customers 1 = context. Customers. Include(c => c. Customer. Жадная загрузка (Eagerly Loading) var customers 1 = context. Customers. Include(c => c. Customer. Adresses); var customers 2 = context. Customers. Include(c => c. Customer. Adresses. Select(ca => ca. Address)); var customers 3 = context. Customers. Include("Customer. Adresses"); • Внутри Include нельзя использовать фильтрацию!!!

Явная загрузка (Explicitly Loading) var customer. Id 1 = context. Customers. Find(1); context. Entry(customer. Явная загрузка (Explicitly Loading) var customer. Id 1 = context. Customers. Find(1); context. Entry(customer. Id 1). Collection(c => c. Customer. Adresses). Load(); context. Entry(customer. Id 1). Collection(c => c. Customer. Adresses). Query(). Where(ca => ca. Address. City == "Ижевск"). Load(); var cust. Address = context. Set(). Find(1); context. Entry(cust. Address). Reference(ca => ca. Address);

Прямое выполнение SQL-команд var customers = context. Customers. Sql. Query( Прямое выполнение SQL-команд var customers = context. Customers. Sql. Query("select * from Sales. LT. Customer where Customer. Id = @Id", new Sql. Parameter("Id", 1)). To. List(); context. Database. Execute. Sql. Command( "update Sales. LT. Customer set Phone = '+79096545' where Customer. Id = 1"); • Можно вызывать хранимые процедуры

ИЗМЕНЕНИЕ ОБЪЕКТОВ ИЗМЕНЕНИЕ ОБЪЕКТОВ

Операции изменения using (var context = new Adwenture. Works. Context()) { var new. Address Операции изменения using (var context = new Adwenture. Works. Context()) { var new. Address = new Address { City = "Ижевск", Address. Line 1 = "К. Маркса 246", Country. Region = "Russia", Postal. Code = "426000", State. Province = "Udmurtia" }; context. Addresses. Add(new. Address); var customer = context. Customers. Find(1); customer. First. Name = "Alister"; customer. Last. Name = "Aben"; customer. Customer. Adresses. Clear(); customer. Customer. Adresses. Add( new Customer. Address { Address = new. Address, Address. Type = "Work" }); context. Addresses. Remove(context. Addresses. Find(1)); context. Save. Changes(); }

Состояние сущности Member Added Deleted Detached Modified Unchanged Description Только что добавленная. После сохранения Состояние сущности Member Added Deleted Detached Modified Unchanged Description Только что добавленная. После сохранения добавляется в базу и переходит в Unchanged Помечена как удаленная. После сохранения удаляется из базы и переходит в состояние Detached Состояние сущности не отслеживается EF Одно из полей сущности было изменено. После сохранения в базе переходит в Unchanged Объект не менялся. Сохранение контекста на нем никак не отразится

Change Tracking API • 2 API: – Object. Context API (класс System. Data. Objects. Change Tracking API • 2 API: – Object. Context API (класс System. Data. Objects. Object. State. Manager) – Db. Context API (класс System. Data. Entity. Infrastructure. Db. Change. Tracker) • обертка над Object. Context • менее функционален • Внутреннее представление сущности: – System. Data. Objects. Object. State. Entry – System. Data. Entity. Infrastructure. Db. Entity. Entry var customer = context. Customers. Find(1); var db. Entry = context. Entry(customer); ((IObject. Context. Adapter)context). Object. Context. Object. State. Manager. Get. Object. State. Entry(customer); var obj. Entry = context. Entry(customer); Console. Write. Line("{0} {1}", db. Entry. State, obj. Entry. State);

Отслеживание изменений (для Db. Context API) • Snapshot Mechanism – метод Detect. Changes – Отслеживание изменений (для Db. Context API) • Snapshot Mechanism – метод Detect. Changes – вызывается в методах • Add, Attach, Find, Local, Remove в Db. Set • Get. Validation. Errors, Entry, Save. Changes в Db. Context • Entries в Db. Change. Tracker – исходные значения через Original. Values в Db. Entity. Entry – для улучшения производительности рекомендуется отключать при массовых изменениях try { context. Configuration. Auto. Detect. Changes. Enabled = false; foreach (var c in new. Customers) { context. Customers. Add(c); } } finally { context. Configuration. Auto. Detect. Changes. Enabled = true; }

Отслеживание изменений (для Db. Context API) • Change-tracking proxy objects – для каждого загружаемого Отслеживание изменений (для Db. Context API) • Change-tracking proxy objects – для каждого загружаемого объекта в реальности создается Proxy-объект – требования к объектам: • класс должен быть объявлен как – public – не sealed и не abstract – с публичным или защищенным конструктором • каждое свойство должно – быть public и virtual – иметь getter и setter (оба публичные) – вместо new следует использовать System. Data. Entity. Db. Set. Create метод

НАСТРОЙКИ НАСТРОЙКИ

Настройки в app. config • Строки подключения – по умолчанию имя строки подключения = Настройки в app. config • Строки подключения – по умолчанию имя строки подключения = имя класса контекста • Прочие настройки в System. Data. Entity. Internal. Config. File – EF 4. 3 Configuration File Settings

ПРОЧИЕ ВОЗМОЖНОСТИ ПРОЧИЕ ВОЗМОЖНОСТИ

Инициализация базы • Несколько стратегий – Create. Database. If. Not. Exists – Drop. Create. Инициализация базы • Несколько стратегий – Create. Database. If. Not. Exists – Drop. Create. Database. Always – Drop. Create. Database. If. Model. Changes – Migrate. Database. To. Latest. Version • Могут переопределяться Database. Set. Initializer(new Create. Database. If. Not. Exists()); using (var context = new Adwenture. Works. Context()) { }

Миграция базы • Code First Migrations public class Migration : Db. Migration { public Миграция базы • Code First Migrations public class Migration : Db. Migration { public override void Up() { this. Add. Column("Customer", "Address. Line 2", c => c. String()); } public override void Down() { this. Drop. Column("Customer", "Address. Line 2"); } }