Saturday 22 January 2011

Entity Framework 4 “Code First” II

Сьогодні у нас спочатку теорія.

Для того щоб рухатись далі у вивченні EF CFнам необхідно уточнити для себе декілька базових речей. Почнемо ми мабуть з того що таблиці в базах даних можуть бути зв’язані між собою трьома видма звязків:

  • Один до одного – це зв’язок який наприклад може бути створеним між двома таблицями, нехай перша буде називатись Post а друга Content. В першій таблиці будуть міститись основні дані поста і його короткий опис а повний текст поста буде міститись у другій таблиці. Таким чином ми зможемо на головну сторінку завантажувати лише необхідну нам інформацію а детальну інформацію будемо підвантажувати лише за необхідності.
  • Один до багатьох – це звя’зов коли один запис з першої таблиці буде містити багато записів в іншій таблиці. Для прикладу розглянемо все ті ж пости, добавивши до них можливість коментування ми знаємо що один пост може містити багато коментарів, що і відображає відношення один до багатьох.
  • Багато до багатьох – це третій і послідній тип зв’язку, він передбачає можливість зв’язку яку можна собі уявити як наприклад пост і теги. Один пост може бути пов’язаний з багатьма тегами і в той же час теги можуть бути пов’язані з багатьма постами.

Ці приклади зв’язків дещо надумані але цілком виконують покладені на них роз’яснювальні функції так що можемо рухатись далі.

Звя’зки можуть бути одно та двонаправленими. Це коли наприклад пост знає список коментарів які йому належать але сам коментар не знає до якого поста він належить. Також можна реалізувати коментарі так що вони знатимуть до якого поста вони належать, але це не завжди правильно і в таких ситуаціях рішення стоїть за вами.

Ключове поле – це поле по якому унікально ідентифікуються записи в таблиці. В основному воно використовується для зв’язку таблиць. Поле в іншій таблиці до якого ми створюємо зв’язок називається зовнішнім ключем, воно не обов’язково повинно бути унікальним. Якщо воно унікальне то ми отримуєом зв’язок один до одного а якщо не унікальне то один до багатьох.

Тепер код

Сьогодні ми попрацюємо з іншою моделлю а ніж ми працювали в попередньому пості. Це не повинно бути ні для кого проблемою так як ця модель буде трохи простішою, і краще підходить для теоретичного засвоєння. Для початку створимо новий проект ASP MVC 3. Як це робити я вже писав у попередніх постах, підключимо скафолдінг і ентіті фреймворк як було написано в попередньому пості. Створимо модель PostEntities в папці Models:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace EFCF_Demo.Models
{
  public class Post
  {
    [Key]
    public int ID { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public string Author { get; set; }
    public DateTime PublishDate { get; set; }
    public int Rating { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
}
  public class Comment
  {
    [Key]
    public int CommentID { get; set; }
    public int PostID { get; set; }
    public string UserName { get; set; }
    public string CommentText { get; set; }
    public int Rating { get; set; }
    public DateTime CommentDate { get; set; }
  }
  public class PostEntities : DbContext
  {
    public DbSet<Post> Posts { get; set; }
    public DbSet<Comment> Comments { get; set; }
  }
}

Тепер згенеруємо контроллер та сторінки командою “Scaffold-Controller -ModelType Post -ContextType PostEntities”. Все що нам необхідне для початку роботи вже є. Тепер для спрощення навігації добавимо пункт в меню сайту для того щоб мати прямий доступ до нашого згенерованого контроллеру, для цього в файлі _Layout.cshtml добавимо до меню один пункт:

<ul id="menu">
<li>@Html.ActionLink("Post", "Index", "Post")</li>
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
</ul>

А в файлі Global.asax змінимо стрічку :

new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults

на

new { controller = "Post", action = "Index", id = UrlParameter.Optional } // Parameter defaults

Сьогодні ми не будемо заморочуватись з веб матріксом і налаштуємо пряме створення бази даних зразу ж в SQL Server. Все що нам для цього треба це добавити стрічку підключення в Web.config наступного вигляду:

 <add connectionString="Data Source=[DATASOURCE_NAME];Initial Catalog=EFCF_Demo.Models.PostEntities;Integrated Security=True" name="EFCF_Demo.Models.PostEntities" providerName="System.Data.SqlClient" />

[DATASOURCE_NAME] – в моєму випадку це назва мого компютера (bats-pc) відповідно вам це треба замінити на свої дані, їх можна взяти з вікна підключення до SQL Server:

image

Тепер запускаємо проект:

Як бачимо все працює. тепер давайте добавимо запис до бази даних і подивимось на згенеровану базу.

Для цього нам необхідно підключитись до сервера баз даних через Management Studio відкрити гілку з нашою базою даних і додати нову діаграму в відповідну папку:

Як і можна було очіквати ми бачимо дві таблиці і зв’язок між ними який показує що один пост може містити багато коментарів(знак безкінечності на звязку біля таблиці коментарів).

Тепер добавляємо зв’язок один до одного, для цього вводимо в нашу модель нову таблицю:

namespace EFCF_Demo.Models
{
  public class Post
  {
    [Key]
    public int ID { get; set; }
    public string Title { get; set; }
    public string MiniContent { get; set; }
    public string Author { get; set; }
    public DateTime PublishDate { get; set; }
    public int Rating { get; set; }
    public Content MainContent { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
  }
  public class Content
  {
    public int ID { get; set; }
    public string FullContent { get; set; }
  }
  public class Comment
  {
    [Key]
    public int CommentID { get; set; }
    public int PostID { get; set; }
    public string UserName { get; set; }
    public string CommentText { get; set; }
    public int Rating { get; set; }
    public DateTime CommentDate { get; set; }
  }
  public class PostEntities : DbContext
  {
    public DbSet<Post> Posts { get; set; }
    public DbSet<Content> Contents { get; set; }
    public DbSet<Comment> Comments { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
      modelBuilder.Entity<Post>().HasOptional(u => u.MainContent).WithRequired();
    }
  }
}

Для цього ми використали не атрибути а Fluent API. Після запуску проекту наша база даних буде мати наступну структуру:

Це якраз те що нам потрібно. Тепер нам залишилось реалізувати зв’язок багато до багатьох і для цього ми знову трошки підправимо нашу модель:

namespace EFCF_Demo.Models
{
  public class Post
  {
    [Key]
    public int ID { get; set; }
    public string Title { get; set; }
    public string MiniContent { get; set; }
    public string Author { get; set; }
    public DateTime PublishDate { get; set; }
    public int Rating { get; set; }
    public Content MainContent { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }
  }
  public class Content
  {
    public int ID { get; set; }
    public string FullContent { get; set; }
  }
  public class Tag
  {
    public int TagID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
  }
  public class Comment
  {
    [Key]
    public int CommentID { get; set; }
    public int PostID { get; set; }
    public string UserName { get; set; }
    public string CommentText { get; set; }
    public int Rating { get; set; }
    public DateTime CommentDate { get; set; }
  }
  public class PostEntities : DbContext
  {
    public DbSet<Post> Posts { get; set; }
    public DbSet<Content> Contents { get; set; }
    public DbSet<Comment> Comments { get; set; }
    public DbSet<Tag> Tags { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
      modelBuilder.Entity<Post>().HasOptional(u => u.MainContent).WithRequired();
    }
  }
}

Тепер ми добавили новий клас і в ньому створили властивість типу колекція постів, відповідно в класі пост ми добавили колекцію тегів. Далі в діло вступає EFCF який розуміє що це два ініш одного і того ж зв’язку і відповідно створює його додавши в базу даних проміжну таблицю, в якій і будуть зберігатись усі зв’язки між цими таблцями. На діаграмі це буде виглядати наступним чином:

Як бачимо проміжна таблиця дійсно створена і містить ключі з двох поєднуваних таблиць. На цьому основне завдання вважаю виконаним. Продовження буде.

No comments:

Post a Comment