Рис.1. Схема взаємодії компонентів ASP.NET MVC
Контролер (controller) - клас, з якого починається робота програми. Забезпечує зв'язок між моделлю і представленням. Отримавши дані, що вводяться користувачем, контролер виходячи з внутрішньої логіки при необхідності звертається до моделі і генерує відповідне представлення. Представлення (view) - це візуальна частина (користувальницький інтерфейс) додатка - наприклад, html-сторінка, через яку користувач, що зайшов на сайт, взаємодіє з веб-додатком. Модель (model) - набір класів, що описують логіку використання даних.
Переваги MVC над WebForms: Поділ відповідальності. Зручне тестування. Відповідність протоколу HTTP. Гнучкість. Шаблоны приложения MVC 4 Internet Application. Intranet Application. Empty. Basic. Mobile Application. Web API. Single Page Application. Facebook Application.
Структура проекта MVC 4 Controllers Models Views App_Data Файл Global.asax и папка App_Start Файл Web.config Content Папки Images и Scripts
Все сущности в приложении принято выделять в отдельные модели. Модели представляют собой простые классы и располагаются в проекте в каталоге Models.
Всі сутності БД в додатку виділяють в окремі моделі. Моделі - прості класи що розташовуються в каталозі Models. Модель, що відображує книгу та її покупку Entity Framework: 1.public class Book 2.{ 3. // ID книги 4. public int Id { get; set; } 5. // назва книги 6. public string Name { get; set; } 7. // автор книги 8. public string Author { get; set; } 9. // ціна 10. public int Price { get; set; } 11.}
1.public class Purchase 2.{ // ID покупки 3. public int PurchaseId { get; set; } 4. // им’я покупця 5. public string Person { get; set; } 6. // адреса покупця 7. public string Address { get; set; } 8. // ID книги 9. public int BookId { get; set; } 10. // дата покупки 11. public DateTime Date { get; set; } 12.}
1.using (SqlConnection sqlConn = new SqlConnection(connectionString)) { 2. using (SqlDataAdapter sqlAdapter = new SqlDataAdapter("Select * from Books", sqlConn)) 3.{ 4. DataTable dataTable = new DataTable(); 5. sqlAdapter.Fill(dataTable); 6. listView.DataSource = dataTable; 7. listView.DataBind(); 8. } 9.} Таблиця що відображує книгу та її покупку ADO.Net
1.using (SqlConnection sqlConn = new SqlConnection(connectionString)) { 2. using (SqlCommand cmd = new SqlCommand("Select * from Books where Id = 1", sqlConn)) 3. { 4. sqlConnection.Open(); 5. using (SqlDataReader rd = cmd.ExecuteReader()) { 6. rd.Read(); 7. bookTitle.Text = rd["Title"].ToString(); 8. bookAuthors.Text = rd["Authors"].ToString(); 9. } 10.} 11.} Таблиця що відображує книгу та її покупку об’єкт SqlDataReader
public class Book { public int Id { get; set; } public string Title { get; set; } public string Authors { get; set; } public int PublisherId { get; set; } }
public class Book { public int Id { get; set; } public string Title { get; set; } public string Authors { get; set; } public int PublisherId { get; set; } } Модель, що відображує книгу та її покупку MVC
public class DatabaseTables { public Book LoadBook(int id) { Book book = null; using (SqlConnection sqlConn = new SqlConnection(connectionString)) { string query = string.Format("Select * from Books where Id = %1", id); using (SqlCommand cmd = new SqlCommand(query, sqlConn))
{ sqlConnection.Open(); using (SqlDataReader rd = cmd.ExecuteReader()) { rd.Read(); book = new Book(); book.Id = (int)rd["Id"]; book.Title = rd["Title"].ToString(); book.Authors = rd["Authors"].ToString(); book.PublisherId = (int)rd["PublisherId"]; } return book; }
Відповідність успадкування таблицями в базі даних Таблиця для кожного конкретного типу (Table per concrete type або TPC) Таблиця для кожного типу (Table per type або TPT) Таблиця для ієрархій (Table per hierarchy або TPH)
<add name="BookCatalogEntities" 3. connectionString=« metadata=res://*/DBFirstCatalogModel.csdl| res://*/DBFirstCatalogModel.ssdl| res://*/DBFirstCatalogModel.msl; 4. provider=System.Data.SqlClient; 5. provider connection string=" 6. data source=(local); 7. initial catalog=BookCatalog; 8. integrated security=True; 9. multipleactiveresultsets=True; 10. App=EntityFramework"" 11. providerName="System.Data.EntityClient" />
<add name="CatalogContext" connectionString="Data Source=(local); Initial Catalog=BookCatalog; Integrated Security=true;" providerName="System.Data.SqlClient" />
var newConnection = new EntityConnectionStringBuilder() { Metadata res://*/DBFirstCatalogModel.ssdl| res://*/DBFirstCatalogModel.msl", Provider ProviderConnectionString source=(local); Initial catalog=BookCatalog; Integrated security=true; multipleactiveresultsets=true; app=entityframework" };
using (var context = new ObjectContext(newConnection.ConnectionString)) { var catalog = context.CreateObjectSet (); var languages = context.CreateObjectSet (); var publishers = context.CreateObjectSet (); var tags = context.CreateObjectSet (); // Запросить данные... }
1.namespace BookCatalog.Models.DbContext 2.{ 3. using System.Data.Entity; 4. using BookCatalog.Models; 5. public class CatalogContext : DbContext 6. { 12. public DbSet Tags { get; set; } 13. public DbSet Publishers { get; set; } 14. public DbSet Languages { get; set; } 15. public DbSet Books { get; set; } 16. } 17.}
<add name="CatalogContext" 6. connectionString="Data source=|DataDirectory|\BooksCatalog.sdf" 7. providerName="System.Data.SqlServerCe.4.0" />
<add name="CatalogContext" connectionString="Data Source=(local); Initial Catalog=BookCatalog; Integrated Security=true;" providerName="System.Data.SqlClient" />
1.namespace BookCatalog.Models 2.{ 3. using System.Collections.Generic; 4. public class Tag 5. { 6. public int Id { get; set; } 7. public string Text { get; set; } 8. public virtual ICollection Books { get; set; } } }
1.namespace BookCatalog.Models 2.{ using System; 3. using System.Collections.Generic; 4. public class BookDetails 5. { public int LanguageId { get; set; } 8. public int? PublisherId { get; set; } public virtual Language Language { get; set; } 12. public virtual Publisher Publisher { get; set; } 13. } 14.}
1.public class BookDetails 2.{ public int? PublisherId { get; set; } public virtual Publisher Publisher { get; set; } 7.} 8. public class Publisher 9.{ 10. public int Id { get; set; } public virtual ICollection Books { get; set; } 13.}
1.public class BookDetails 2.{ public virtual ICollection Tags { get; set; } } public class Tag 10.{ public virtual ICollection Books { get; set; } 13.}
[Table(string name, Schema = string)] [Column(string name, Order = int, TypeName = string)] [Key] [Required] [StringLength(int maximumLength, MinimumLength = int)] [MaxLength(int length)] [Timestamp] [ForeignKey(string name)] [InverseProperty(string property)] [DatabaseGenerated(DatabaseGeneratedOption databaseGeneratedOption)] [NotMapped]
1.public class Gamer 2.{ public int Id { get; set; } 3. public string Name { get; set; } 4. public int MainId { get; set; } 5. public int? ReserveId { get; set; } 6. [InverseProperty("Gamers")] 7. [ForeignKey("MainId")] 8. public virtual Team GamersTeam { get; set; } 9. [InverseProperty("Reserve")] 10. [ForeignKey("ReserveId")]
1. public virtual Team ReserveTeam { get; set; } } 2. public class Team 3.{ public int Id { get; set; } 4. public string Name { get; set; } 5. public virtual ICollection Gamers { get; set; } 6. public virtual ICollection Reserve { get; set; } }
1.namespace BookCatalog.Models 2.{ using System; 3. using System.Collections.Generic; 4. using System.ComponentModel.DataAnnotations; 5. using BookCatalog.Resources.Models; 6. [Table("Catalog")] 7. public class BookDetails 8. { public int Id { get; set; } 9. [Display(Name = "Title", ResourceType = typeof(BookDetailsRes))] 10. [Required] 11. [StringLength(128)] 12. public string Title { get; set; } [Display(Name = "Author", ResourceType = typeof(BookDetailsRes))]
14. [Required] 15. [StringLength(128)] 16. public string Author { get; set; } public int LanguageId { get; set; } public int? PublisherId { get; set; } [Display(Name = "PublishedAt", ResourceType = typeof(BookDetailsRes))] 23. [Required] 24. public DateTime PublishedAt { get; set; } [Display(Name = "Url", ResourceType = typeof(BookDetailsRes))] 27. [Required] 28. [StringLength(256)] 29. public string Url { get; set; }
27. [Display(Name = "Description", ResourceType = typeof(BookDetailsRes))] 28.[Required] 29. [StringLength(512)] 30. public string Description { get; set; } 31.[Display(Name = "Rating", ResourceType = typeof(BookDetailsRes))] 32. public int? Rating { get; set; } 33.[Display(Name = "IsFree", ResourceType = typeof(BookDetailsRes))] 34. [Required] 35. public bool IsFree { get; set; }
35. [Display(Name = "IsVisible", ResourceType = typeof(BookDetailsRes))] 36. [Required] 37. public bool IsVisible { get; set; } 38. [Display(Name = "Tags", ResourceType = typeof(BookDetailsRes))] 39. public virtual ICollection Tags { get; set; } 40. [Display(Name = "Language", ResourceType = typeof(BookDetailsRes))] 41. public virtual Language Language { get; set; } 42. [Display(Name = "Publisher", ResourceType = typeof(BookDetailsRes))] 43. public virtual Publisher Publisher { get; set; } 44. } }
1.namespace BookCatalog.Models 2.{ using System.Collections.Generic; 3. using System.ComponentModel.DataAnnotations; 4. using BookCatalog.Resources.Models; 5. public class Language 6. {public int Id { get; set; } 7. [Display(Name = "Name", ResourceType = typeof(LanguageRes))] 8. [Required] 9. [StringLength(64)] 10. public string Name { get; set; } 11. [Display(Name = "Books", ResourceType = typeof(LanguageRes))] 12. public virtual ICollection Books { get; set; } 13. } }
1.namespace BookCatalog.Models 2.{ using System.Collections.Generic; 3. using System.ComponentModel.DataAnnotations; 4. using BookCatalog.Resources.Models; 5. public class Publisher 6. { public int Id { get; set; } 7. [Display(Name = "Title", ResourceType = typeof(PublisherRes))] 8. [Required] 9. [StringLength(128)] 10. public string Title { get; set; } 11. [Display(Name = "Homepage", ResourceType = typeof(PublisherRes))] 12. [StringLength(256)] 13. public string Homepage { get; set; } 14. [Display(Name = "Books", ResourceType = typeof(PublisherRes))] 15. public virtual ICollection Books { get; set; } } }
1.namespace BookCatalog.Models 2.{ using System.Collections.Generic; 3. using System.ComponentModel.DataAnnotations; 4. using BookCatalog.Resources.Models; 5. public class Tag 6. {public int Id { get; set; } 7. [Display(Name = "Text", ResourceType = typeof(TagRes))] 8. [Required] 9. [StringLength(32)] 10. public string Text { get; set; } 11. [Display(Name = "Books", ResourceType = typeof(TagRes))] 12. public virtual ICollection Books { get; set; } 13. } 14.}
modelBuilder.Entity ().HasRequired(e => e.ReserveTeam).WithMany(t => t.Reserve).HasForeignKey(e => e.ReserveId).WillCascadeOnDelete(false);
namespace BookCatalog.Models.DbContext { using System.Data.Entity; using BookCatalog.Models; public class CatalogContext : DbContext { public DbSet Tags { get; set; } public DbSet Publishers { get; set; } public DbSet Languages { get; set; } public DbSet Books { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) {base.OnModelCreating(modelBuilder); // место для вызовов Entity Framework Fluent API } } }
modelBuilder.Entity ().HasKey(b => b.Id); modelBuilder.Entity ().HasKey(p => new { p.Title, p.Homepage } ); modelBuilder.Entity ().Property(p => p.Title).HasMaxLength(128); modelBuilder.Entity ().Property(p => p.Title).IsRequired(); modelBuilder.Entity ().Ignore(t => t.TotalTagsLenght); modelBuilder.Entity ().Property(t => t.Author).IsUnicode(false); modelBuilder.Entity ().Property(t => t.PublishedAt).HasColumnName("PublishDate");
modelBuilder.Entity ().Property(t => t.Author).HasColumnOrder(2); modelBuilder.Entity ().Property(t => t.Author).HasColumnType("varchar"); modelBuilder.Entity ().Property(t => t.Address.Street).HasMaxLength(128);
modelBuilder.Entity ().Property(t => t.Title).IsRequired().HasMaxLength(128).HasColumnName("BookTitle").HasColumnOrder(2); modelBuilder.Entity ().ToTable("Catalog"); modelBuilder.Ignore (); modelBuilder.ComplexType ();
modelBuilder.Entity ().Map (m =>m.Requires("Type").HasValue("BaseType")).Map (m => m.Requires("Type").HasValue("ChildType")); modelBuilder.Entity ().Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); modelBuilder.Entity ().Map(m => { m.MapInheritedProperties(); m.ToTable("ChildType"); }); modelBuilder.Entity ().ToTable("BaseType"); modelBuilder.Entity ().ToTable("ChildType");
modelBuilder.Entity ().Map(m => {m.Properties(b => new { b.Id, b.Title, b.Author, b.Url }); m.ToTable("Catalog"); }).Map(m => { m.Properties(b => new { b.Description, b.IsFree, b.IsVisible, b.LanguageId, b.PublishedAt, b.PublisherId, b.Rating }); m.ToTable("BookDetails"); });
modelBuilder.Entity ().HasKey(g => g.ArbitterID); modelBuilder.Entity ().HasRequired(a => a.Game).WithRequiredPrincipal(t => t.Arbitter); modelBuilder.Entity ().ToTable("Games");
modelBuilder.Entity ().HasRequired(g => g.Arbitter).WithOptional(a => a.Game); modelBuilder.Entity ().HasRequired(a => a.Game).WithRequiredPrincipal(g => g.Arbitter); modelBuilder.Entity ().HasOptional(a => a.Game).WithOptionalPrincipal(g => g.Arbitter); modelBuilder.Entity ().HasMany(b => b.Tags).WithMany(t => t.Books);
modelBuilder.Entity ().HasRequired(a => a.Game).WithRequiredPrincipal(); modelBuilder.Conventions.Remove (); modelBuilder.Entity ().HasRequired(g => g.GameTypes).WithMany(g => g.Games).HasForeignKey(g => g.GTId);
namespace BookCatalog.Models.DbContext { using System; using System.Data.Entity; public class CatalogInitializer : DropCreateDatabaseIfModelChanges { protected override void Seed(CatalogContext context) { base.Seed(context); var englishLang = new Language() { Name = "English" }; context.Languages.Add(englishLang); var russianLang = new Language() { Name = "Russian" }; context.Languages.Add(russianLang); var microsoftPress = new Publisher() { Title = "Microsoft Press", };
context.Publishers.Add(microsoftPress); var tagVS2010 = new Tag() { Text = "VS2010" }; context.Tags.Add(tagVS2010); var tagASPNET = new Tag() { Text = "ASP.NET" }; context.Tags.Add(tagASPNET); var tagMVC = new Tag() { Text = "MVC" }; context.Tags.Add(tagMVC); var tagCSharp = new Tag() { Text = "C#" }; context.Tags.Add(tagCSharp); var tagWP7 = new Tag() { Text = "WP7" }; context.Tags.Add(tagWP7);
context.Books.Add(new BookDetails() { Title = "ASP.NET Web Pages with Razor Syntax", Author = "P. Pelland, P. Pare, Ken Haines", Language = englishLang, Publisher = microsoftPress, PublishedAt = new DateTime(2010, 09, 10), Url microsoft-visual-studio-2010.aspx", Description = "For developers moving from Visual Studio 2003,2005,2008 to Visual Studio 2010.", Rating = 4, Tags = new Tag[1] { tagVS2010 }, IsFree = true, IsVisible = true });
context.Books.Add(new BookDetails() { Title = "Programming Windows Phone 7", Author = "Charles Petzold", Language = englishLang, Publisher = microsoftPress, PublishedAt = new DateTime(2010, 10, 28), Url Description = "This book is a gift from the Windows Phone 7 team at Microsoft to the programming community.", Rating = 5, Tags = new Tag[3] { tagVS2010, tagCSharp, tagWP7 }, IsFree = true, IsVisible = true }); }
protected void Application_Start() { System.Data.Entity.Database.SetInitializer( new BookCatalog.Models.DbContext.CatalogInitializer()); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }