net framework и С#, весна 2015: data sources

44
Толстиков Никита [email protected] ASP.NET и БД 30.04.2015 1 ASP.NET

Upload: cs-center

Post on 17-Jul-2015

207 views

Category:

Documents


0 download

TRANSCRIPT

Толстиков Никита

[email protected]

ASP.NET и БД

30.04.2015 1ASP.NET

План лекции

• SQL via C#

• ORM

• Паттерн репозиторий

30.04.2015 Толстиков Никита 2ASP.NET

Реляционная БД

• Реляционная база данных — база

данных, основанная на реляционной

модели данных.

• Реляционность – это отношения (связи)

от англ. relation.

• Реляционная база данных – это таблицы

и отношения между ними

30.04.2015 Толстиков Никита 3ASP.NET

Схема БД

30.04.2015 Толстиков Никита 4ASP.NET

Таблица

• Таблица состоит из столбцов и строк.

• Столбцы имеют свойства – имя, тип данных.

• Таблицы должны обладать следующими свойствами:

– у таблицы есть имя (уникальное)

– нет двух одинаковых строк

– столбцы имеют разные наименования (нет двух одинаковых столбцов)

– порядок строк в таблице произвольный

• Структуру таблицы представдена в виде:– Имя столбца

– Тип данных для этого столбца

30.04.2015 Толстиков Никита 5ASP.NET

Связи

• Между таблицами существуют связи (relation).

• Для установки связи необходимо иметь следующее:

– Первичный ключ – это набор столбцов (атрибутов) таблицы, однозначно определяющих уникальность строки.

– Внешний ключ – это набор столбцов (атрибутов) таблицы, которые однозначно определяют уникальность строки в другой таблице.

• Прописана связь между первичным ключом и внешним ключом

30.04.2015 Толстиков Никита 6ASP.NET

Связи

• Связи бывают трех типов:

– Один-к-одному

– Один-ко-многим

– Многие-ко-многим

30.04.2015 Толстиков Никита 7ASP.NET

Схема БД

30.04.2015 Толстиков Никита 8ASP.NET

SQL Express LocalDB

• Начиная с версии Visual Studio 2012 в

комплекте устанавливается SQL Server

Express LocalDB

• В VisualStudio:

– VIEW -> Server Explorer (Ctrl+W,L) ->

DataConnections -> Add Connections.. ->

(localdb)\v11.0 (версия сервера)

30.04.2015 Толстиков Никита 9ASP.NET

SqlConnection

• System.Data.SqlClient.SqlConnection – BCL класс отвечающий за соединение с MsSqlServer

• Для соединения с другими базами данных поддерживающих OLE DB используйте OleDbConnection• SqlConnection – это ресурс

• Для ускорения работы используется пул соединений

• Для подключения к базе данных необходима ConnectionString

• Соединение не всегда открыто при создании

30.04.2015 Толстиков Никита 10ASP.NET

ConnectionString

• Строка содержащая информацию о том с чем и как установить соединение

• Представляет из себя пары ключ=знчение;

• Основные параметры:– Server или Data Source – адрес СУБД

– Database – имя базы данных

– Integrated Security – использовать или нет windows аккаунт

– User Id – имя аккаунта на сервере

– Password – пароль от аккаунта

• Полный список параметров здесь

• Список параметров может меняться от версии к версии

30.04.2015 Толстиков Никита 11ASP.NET

@"Server=(localdb)\v11.0;Database=test_monsters_db;

Integrated Security=true"

SqlConnection

30.04.2015 Толстиков Никита 12ASP.NET

var connection = new System.Data.SqlClient.SqlConnection(@"Server=(localdb)\v11.0;Database=test_monsters_db;Integrated Security=true");

using (connection){

connection.Open();Console.WriteLine(connection.State);

}

SqlCommand

• SqlCommand – класс ответственный за выполнение команд через соединение

• Свойство CommandType определяет тип:– CommandType.Text Sql текст. (Default.)

– CommandType.StoredProcedure для вызова процедуры по имени

– CommandType.TableDirect для получения всей таблицы(OleDb)

• 3 способа исполнить команду:– ExecuteNonQuery – возвращает кол-во измененных строк

– ExecuteScalar – возвращает один объект в ячейке [0,0]таблицы результата

– ExecuteReader – возвращает таблицу результата обернутуюSqlDataReader

• SqlCommand для исполнения ad hoc sql поддерживает параметры

30.04.2015 Толстиков Никита 13ASP.NET

SqlCommand

30.04.2015 Толстиков Никита 14ASP.NET

var connection = new SqlConnection(@"Server=(localdb)\v11.0;Database=test_monsters_db;Integrated Security=true");

using (connection){

connection.Open();Console.WriteLine("Connection state: {0}",

connection.State);var command = new SqlCommand(

"insert into dbo.Monstersvalues ('MegaLuckyMonster', 1, 100, '2010.1.1')",connection);

using (command){

int updated = command.ExecuteNonQuery();Console.WriteLine("Updated {0} rows", updated);

}}

SqlDataReader

• SqlDataReader – класс инкапсулирующий результирующую таблицу

• Ресурс

• Содержит кол-во столбцов в таблице результате

• В один момент времени хранит только одну строчку

• Для получения следующей строчки нужно выполнить Read(), которая проинициализирует реадер и вернет true, или вернет false если строк не осталось

30.04.2015 Толстиков Никита 15ASP.NET

SqlDataReader

30.04.2015 Толстиков Никита 16ASP.NET

using (var command = new SqlCommand("select * from dbo.Monsters", connection)){

command.CommandType = CommandType.Text;using (var reader = command.ExecuteReader()){ //Columns Names

for (int i = 0; i < reader.FieldCount; i++){

Console.WriteLine("Column {0} - {1}", i, reader.GetName(i));

}while (reader.Read()){

Console.WriteLine("Monster: {0} {1} {2} {3}", (int)reader[0] //Monster Id

, (string)reader["Name"] //Monster Name, reader.GetDouble(3) //Monster LuckRate, reader.GetFieldValue<DateTime>(4) //Created Date);

}}

}

ORM

• Object-relational mapping – техника для

доступа к базам данных из ООП языков

программирования

30.04.2015 Толстиков Никита 17ASP.NET

ORM

• Существует множество реализаций

ORM для разных языков:

– Hibernate – Java

– Active Record – Ruby on Rails

– Doctrine – PHP

– SQLAclchemy – Python

30.04.2015 Толстиков Никита 18ASP.NET

ORM in .NET

• В С# удобно использовать ORM из-за

LINQ и query DSL

• Реализации:

– EntityFramework от Microsoft

– LinqToSql от Microsoft

– Data Access от Telerik

– NHibernate от open source

30.04.2015 Толстиков Никита 19ASP.NET

ORM

Отзывы об использовании ORM:

• Плюсы:

– Добавляет прослойку между СУБД и кодом

– Упрощает работу с базами данных

• Минусы:

– Добавляет накладные расходы

– Сложно оптимизировать

– Есть тонкие моменты

30.04.2015 Толстиков Никита 20ASP.NET

Entity Framework

• ORM Framework от Microsoft

• NuGet – менеджер пакетов для

VisualStudio

• Tools -> Library Package Manager -> Library

Package Manager Console

Install-Package EntityFramework

30.04.2015 Толстиков Никита 21ASP.NET

Entity Framework

• DbContext – основной класс никапсулирующий работу с базой данных

• Для работы с собственной базой нужно унаследоваться от него и перечислить объекты БД

• Сущность – это обычный класс

• DbContext – управляет таблицами, которые представлены как DbSet ваших табличных сущностей

30.04.2015 Толстиков Никита 22ASP.NET

Управление сущностями

• Управленеие сущностями происходит чере через DbSet’ы

• Интерфейс работы DbSet‘ов напоминает интерфейс работы с коллекциями

• DbSet реализует интерфейс IQuerable• SbContext – проксирует объекты для ускорения работы

• По умолчанию подгружаются только поля таблицы

• Для сохранения изменений нужно вызвать SaveChanges

30.04.2015 Толстиков Никита 23ASP.NET

Управление сущностями

• Add – добавляет сущность в БД

• Remove – удалить сущность из БД

• Attach – добавить сущность под контроль

DbContext

• Detach – явно удалить сущность из контекста

30.04.2015 Толстиков Никита 24ASP.NET

DbContext

• Существует 3 способа получить

DbContext:

– Создать все классы сущностей и наследника

DbContext в коде (Code First)

– Создать базу при помощи SQL и

сгенерировать необходимые классы в коде

(DB First)

– Создать модель, на основе которой

сгенерируется и то и другое (Model First)

30.04.2015 Толстиков Никита 25ASP.NET

Code First

• Создание сущностей:

– Типы из C# отображаются на типы SQL здесь

– Для регулирования сопоставления колонок

таблиц и полей класса можно использовать

DataAnnotations или FluentAPI

• Работа с контекстом:

– Можно управлять способом инициализации

БД для контекста через свойство

Database.SetInitializer

30.04.2015 Толстиков Никита 26ASP.NET

DataAnnotations

• Аттрибуты управляющие отображением в базу данных классов сущностей

• Находятся в System.ComponentModel.DataAnnotations• Основные:

– Key – определяет PRIMARY KEY таблицы. Может быть составным

– Required – аналогично NOT NULL

– MaxLength и MinLength мощность типа в байтах

– NotMapped – не отображать в БД

– ComplexType – создание под сущности в той же таблице

– ConcurrencyCheck и TimeStamp – позволяют использовать optimisctic concurency

– Table и Column – позволяют задать имена таблиц и колонок

– DatabaseGenerated – поле обновляется базой данных

– Index – создание индексов

– ForeignKey – FOREIGN KEY

30.04.2015 Толстиков Никита 27ASP.NET

FluentApi

• При соблюдении name conventions DataAnnotatinons покрывают практически все случаю отображения

• Для случаев которые не покрываются или вы не согласны с name conventions можно использовать FluentAPI

• Переопределение стандартного поведения происходит в OnModelCreating c использованием DbModelBuilder

• Полный список можно найти здесь

30.04.2015 Толстиков Никита 28ASP.NET

Миграция БД

• Процесс адаптации структуры БД к новой структре полей классов

• Этапы миграции:

– Создается модель базы на основе текущего кода

– Сравнивается модель текущего кода и модель базы последней миграции

– Генерируется код для обновления структуры БД

– Генерируеция новая модель миграции

30.04.2015 Толстиков Никита 29ASP.NET

Миграция БД

• История миграции находится в таблице

__MigrationsHistory

• Миграция:

– Enable-Migrations команда включающая

миграцию

– Add-Migration – создает код для миграции

– Update-Database – применяет последнюю

миграцию

30.04.2015 Толстиков Никита 30ASP.NET

Virtual поля

• Если поле сущности помеченно как

virtual, то EntityFramework может создать

класс наследника

• Это позволяет переопределить свойства

так, что бы сделать их ленивыми

• Такой подход ускоряет нахождение

изменений

30.04.2015 Толстиков Никита 31ASP.NET

ModelFirst

• Подход при котором EntityFramework сам

генерирует все классы на основе модели

• DbFirst Используется когда база данных

уже спроектирована и используется

• Такой подход позволяет разделить

работу на БД и работу над приложением

• Генерация происходит при помощи T4

шаблонов

30.04.2015 Толстиков Никита 32ASP.NET

Выбор модели

30.04.2015 Толстиков Никита 33ASP.NET

Паттерн репозиторий

• Репозиторий – уровень абстракции между бизнесс логикой и контекстом базы данных

• Репозиторий – контролирует доступ к одному виду сущностей

• UnitOfWork – отвечает за то что бы все репозитории использовали один DbContext

30.04.2015 Толстиков Никита 34ASP.NET

Реализация

30.04.2015 Толстиков Никита 35ASP.NET

public interface IRepository<TEntity> : IDisposablewhere TEntity : class

{IEnumerable<TEntity> Get(

Expression<Func<TEntity, bool>> filter = null,string includeProperties = "",Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null);

TEntity GetById(object id);void Insert(TEntity entity);void Delete(object id);void Delete(TEntity entityToDelete);void Update(TEntity entityToUpdate);

}

Реализация

30.04.2015 Толстиков Никита 36ASP.NET

public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class{

internal MonstersContext context;internal DbSet<TEntity> dbSet;

public GenericRepository(MonstersContext context){

this.context = context;this.dbSet = context.Set<TEntity>();

}...

Реализация

30.04.2015 Толстиков Никита 37ASP.NET

public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class{

internal MonstersContext context;internal DbSet<TEntity> dbSet;

public GenericRepository(MonstersContext context){

this.context = context;this.dbSet = context.Set<TEntity>();

}...

Реализация

30.04.2015 Толстиков Никита 38ASP.NET

public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,Func<IQueryable<TEntity>,

IOrderedQueryable<TEntity>> orderBy = null,string includeProperties = "")

{IQueryable<TEntity> query = dbSet;if (filter != null){

query = query.Where(filter);}foreach (var includeProperty in includeProperties.Split

StringSplitOptions.RemoveEmptyEntries)){

query = query.Include(includeProperty);}if (orderBy != null) return orderBy(query).ToList();else query.ToList();

}

Реализация

30.04.2015 Толстиков Никита 39ASP.NET

public virtual void Delete(TEntity entityToDelete){

if (context.Entry(entityToDelete).State == EntityState.Detached){

dbSet.Attach(entityToDelete);}dbSet.Remove(entityToDelete);

}

public virtual void Update(TEntity entityToUpdate){

dbSet.Attach(entityToUpdate);context.Entry(entityToUpdate).State = EntityState.Modified;

}

Реализация

30.04.2015 Толстиков Никита 40ASP.NET

public virtual TEntity GetByID(object id){

return dbSet.Find(id);}

public virtual void Insert(TEntity entity){

dbSet.Add(entity);}

public virtual void Delete(object id){

TEntity entityToDelete = dbSet.Find(id);Delete(entityToDelete);

}

Реализация

30.04.2015 Толстиков Никита 41ASP.NET

public interface IMonsterRepository{

double CalcAvverageLucky();}

public class MonsterRepository : GenericRepository<Monster>, IMonsterRepository

{public MonsterRepository(MonstersContext context) : base(context){}

public double CalcAvverageLucky(){

return DbSet.Sum(m => m.LuckyRate)/DbSet.Count();}

}

IUnitOfWork

30.04.2015 Толстиков Никита 42ASP.NET

public interface IUnitOfWork : IDisposable{

GenericRepository<Monster> DepartmentRepository { get; }GenericRepository<Weapoon> CourseRepository { get; }void Save();

}

UnitOfWork

30.04.2015 Толстиков Никита 43ASP.NET

public class UnitOfWork : IUnitOfWork{

private MonstersContext context = new MonstersContext();private GenericRepository<Monster> departmentRepository;private GenericRepository<Weapoon> courseRepository;

public GenericRepository<Weapoon> CourseRepository{

get{

if (this.courseRepository == null){

this.courseRepository = new GenericRepository<Weapoon>(context);}return courseRepository;

}}

public void Save(){

context.SaveChanges();}

The End

30.04.2015 Толстиков Никита 44ASP.NET