Construindo Aplicações com ASP.NET MVC 2.0 Aula 03 Luiz Alberto Ferreira Gomes Ciência da Computação da PUC Minas
2 Camada responsável por armazenar em um repositório de dados e reconstituir objetos de negócios. um repositório pode ser um banco de dados, um arquivo XML, um arquivo texto ou até mesmo em memória Objetos da camada de persistência fornecem operações para incluir, atualizar, remover e recuperar objetos. podem oferecer também mecanismos para gerenciamento de transações e concorrência da dados. Objetos da camada de persistência não devem conter lógica de negócio.
3 A Camada de Persistência
4 1. Escolha a opção File New Project. Criando a Camada de Persistência 2. Escolha a Versão 3.5 do framework.net. 3. Escolha Visual C# Class Library. 4. Em Name digite QuoteOMatic.Persiste ncia. 5. Em Location digite c:\dev\quoteomatic. 6. Em Solution, escolha Add to solution.
5 1. Selecione com o BDM a camada QuoteOMatic.Pers istencia. Criando a Interface IQuoteRepository 2. Escolha a opção Add Class.
6 1. Em Installed Templates, escolha a opção Visual C# Items Interface. Criando a Interface IQuoteRepository 2. Em Name, digite IQuoteRepository.c s. 3. Para Finalizar, clique em Add.
7 Código da interface IQueryRepository 1. using System.Collections.Generic; 2. using QuoteOMatic.Dominio; 3. namespace QuoteOMatic.Persistencia 4. { 5. public interface IQuoteRepository 6. { 7. IEnumerable<Quote> FindAll(); 8. Quote FindBy(int number); 9. void Add(Quote quote); 10. void Update(Quote quote); 11. } 12. } Para mais informações sobre a interface IEnumerable, visite o endereço: msdn.microsoft.com/pt-br/library/system.collections.ienumerable.aspx
8 Código refatorado da classe Quote 1. namespace QuoteOMatic.Dominio 2. { 3. public class Quote 4. { 5. public Quote(int number, Author author, string contents, int rating) 6. { 7. Number = number; 8. Contents = contents; 9. Author = author; 10. Rating = rating; 11. } 12. public int Number { get; set; } 13. public string Contents { get; private set; } 14. public Author Author { get; private set; } 15. public int Rating { get; private set; } 16. } 17.} A propriedade Number identificara uma citação e a propriedade Rating armazenará a nota total das avaliações da citação
9 Código da classe InMemoryQuoteRepository 1. using System; 2. using System.Collections.Generic; 3. using QuoteOMatic.Dominio; 4. namespace QuoteOMatic.Persistencia 5. { 6. public class InMemoryQuoteRepository : IQuoteRepository 7. { 8. private static readonly List<Quote> FamousQuotes = new List<Quote> 9. { 10. new Quote(1, new Author("Guimarães Rosa") 11., "Quando nada acontece, há um milagre que não estamos vendo.", 0), 12. new Quote(2, new Author("Castro Alves") 13., "Bendito aquele que semeia livros e faz o povo pensar.", 0) 14. }; 15. #region IQuoteRepository Members 16. public IEnumerable<Quote> FindAll() 17. { 18. return FamousQuotes; 19. }
10 Código da classe InMemoryQuoteRepository 1.... 2. public Quote FindBy(int number) 3. { 4. return FamousQuotes.Find(quote => quote.number == number); 5. } 6. public void Add(Quote quote) 7. { 8. quote.number = FamousQuotes.Count + 1; 9. FamousQuotes.Add(quote); 10. } 11. public void Update(Quote quote) 12. { 13. throw new NotImplementedException(); 14. } 15. #endregion 16. } 17.}
11 Código refatorado da classe QuoteService 1. using QuoteOMatic.Persistencia; 2. using QuoteOMatic.Servicos.ViewModels; 3. namespace QuoteOMatic.Servicos 4. { 5. public class QuoteService 6. { 7. private readonly IQuoteRepository _quoterepository; 8. private readonly Random _randomizer = new Random(); 9. public QuoteService() { _quoterepository = new InMemoryQuoteRepository(); } 10. public QuoteViewModel ChooseRandomQuote() 11. { 12. QuoteViewModel result = ReturnEmptyQuote(); 13. Quote[] allquotes = _quoterepository.findall().toarray(); 14. if (allquotes.any()) 15. { 16. int randomindex = _randomizer.next(allquotes.count()); 17. result = new QuoteViewModel(allQuotes[randomIndex]); 18. } 19. return result; 20. } 21....
12 Código refatorado da classe QuoteService 1.... 2. public QuoteViewModel ReturnEmptyQuote() 3. { 4. return new QuoteViewModel(new Quote(0, new Author(""), "", 0)); 5. } 6. public void CreateQuote(string authorname, string contents) 7. { 8. _quoterepository.add(new Quote(0, new Author(authorName), contents, 0)); 9. } 10. } 11.}
Experimento 1 13 Crie a camada QuoteOMatic.Persistencia. Ela deverá referenciar a camada QuoteOMatic. Dominio. Refatore a classe Quote para que ela possa armazenar o número e o total das classificações da citação. Crie a interface IQuoteRepository. Esta interface deverá ser criada na camada QuoteOMatic.Persistencia. Crie a classe InMemoryQuoteRepository que implementará os serviços da interface IQuoteRepository. Esta classe deverá ser criada na camada QuoteOMatic.Persistencia. Refatore a classe QuoteService para que ela utilize a classe InMemoryQuoteRepository. Não se esqueça que a QuoteOMatic.Servicos deverá referenciar a QuoteOMatic. Persistencia. Teste a aplicação Quote-O-Matic. Ela deverá continuar funcionando.
14 1. Selecione a pasta App_Data na camada QuoteOMatic.Visa o.web.mvc. Criando o banco de dados quotes 2. Com o BDM escolha a opção Add New Item.
15 1. Em Installed Templates, Escolha Visual C# SQL Server Database. Criando o banco de dados Quotes 2. Em Name, digite Quotes.mdf. 3. Clique em Add para finalizar.
16 1. Selecione a com BDM a pasta Table o banco de dados Quotes.mdf. Criando a tabela quote. 2. Escolha a opção Add New Table.
17 1. Em Column Name, digite number. Criando o campo number da tabela quote. 2. Em Data Type, escolha a opção int. 3. Em Column Properties, altere a propriedade (Is Identity) para Yes.
18 1. Em Column Name, digite author_name. 2. Em Data Type, escolha a opção varchar(50). Criando o campo author_name da tabela quote.
19 1. Em Column Name, digite contents. 2. Em Data Type, digite o tipo varchar(2000). Criando o campo contents da tabela quote.
20 1. Em Column Name, digite rating. Criando o campo rating da tabela quote. 2. Em Data Type, escolha o tipo int. 3. Em Column Properties, digite 0 (zero) na propriedade Default Value or Binding.
21 1. Clique no disquete para salvar a estrutura da tabela. Criando a tabela quote. 2. Em Enter a name for the table digite quote.
Experimento 2 22 Crie o banco de dados Quotes.
23 Código do construtor da classe InDatabaseQuoteRepository. using System; using System.Collections.Generic; using System.Configuration; using System.Data.SqlClient; using QuoteOMatic.Dominio; namespace QuoteOMatic.Persistencia { public class InDatabaseQuoteRepository : IQuoteRepository { private readonly string _connectionstring; public InDatabaseQuoteRepository() { _connectionstring = ConfigurationManager.ConnectionStrings["QuoteOMaticConnectionString"].ConnectionString; }
24 Código do método FindAll da classe InDatabaseQuoteRepository. 1. #region IQuoteRepository Members 2. public IEnumerable<Quote> FindAll() 3. { 4. IList<Quote> quotes = new List<Quote>(); 5. const string querystring = "SELECT * FROM quote"; 6. using (var connection = new SqlConnection(_connectionString)) 7. { 8. SqlCommand command = connection.createcommand(); 9. command.commandtext = querystring; 10. connection.open(); 11. using (SqlDataReader reader = command.executereader()) 12. { 13. while (reader.read()) 14. { 15. quotes.add(new Quote(Convert.ToInt32(reader["number"]) 16., new Author(reader["author_name"].ToString()) 17., reader["contents"].tostring() 18., Convert.ToInt32(reader["rating"]))); 19. } 20. } 21. } 22. return quotes; 23. }
25 Código do método FindBy da classe InDatabaseQuoteRepository. 1. public Quote FindBy(int number) 2. { 3. Quote quote = null; 4. var querystring = String.Format( 5. "SELECT * FROM quote WHERE number = {0}", number); 6. using (var connection = new SqlConnection(_connectionString)) 7. { 8. SqlCommand command = connection.createcommand(); 9. command.commandtext = querystring; 10. connection.open(); 11. using (var reader = command.executereader()) 12. { 13. if (reader.read()) 14. { 15. quote = new Quote(Convert.ToInt32(reader["number"]) 16., new Author(reader["author_name"].ToString()) 17., reader["contents"].tostring() 18., Convert.ToInt32(reader["rating"])); 19. } 20. } 21. } 22. return quote; 23. }
26 Código do método Add da classe InDatabaseQuoteRepository. 1. public void Add(Quote quote) 2. { 3. const string sql = "INSERT INTO quote " + 4. "(author_name, contents, rating) values " + 5. "(@author_name, @contents, @rating)"; 6. Save(quote, sql); 7. }
27 Código do método Update da classe InDatabaseQuoteRepository. 1. public void Update(Quote quote) 2. { 3. const string sql = "UPDATE quote " + 4. " author_name = @author_name" + 5. ", contents = @contents" + 6. ", rating = rating+@rating " + 7. "where number = @number"; 8. Save(quote, sql); 9. }
28 Código do método Save da classe InDatabaseQuoteRepository. 1. private void Save(Quote quote, string sql) 2. { 3. using (var connection = new SqlConnection(_connectionString)) 4. { 5. SqlCommand command = connection.createcommand(); 6. command.commandtext = sql; 7. command.parameters.add(new SqlParameter("@number", quote.number)); 8. command.parameters.add(new SqlParameter("@author_name", 9. quote.author.name)); 10. command.parameters.add(new SqlParameter("@contents", quote.contents)); 11. command.parameters.add(new SqlParameter("@rating", quote.rating)); 12. connection.open(); 13. command.executenonquery(); 14. } 15. } 16. #endregion 17. } 18.}
29 Configurando o Web.config que está na raiz da camada QuoteOMatic.UI.Web.MVC. 1. <connectionstrings> 2. <add name="quoteomaticconnectionstring" 3. connectionstring="data Source =.\SQLEXPRESS;AttachDbFilename=c:\dev\QuoteOMatic\QuoteOMatic.Visao.Web.MVC\App_Data \Quotes.mdf;Integrated Security=True;User Instance=True" 4. providername="system.data.sqlclient"/> 5. </connectionstrings> Você poderá copiar a connectionstring a partir deste local.
Experimento 3 30 Crie a classe InDatabaseQuoteRepository. Ela deverá implementar os serviços da interface IQuoteRepository e ser armazenada na camada QuoteOMatic.Persistência. Altere o código da classe QuoteServive para utilizar a InDataBaseQuoteRepository ao invés da InMemoryQuoteRepository. Teste a sua aplicação. Ela deverá continuar a funcionar.
31 Caso de Uso Mostrar Citações por Avaliação O caso de uso que agora será desenvolvido e o Mostrar Citações Por Avaliação.
32 Caso de Uso Mostrar Citações Por Avaliação Protótipo essencial do caso de uso.
A Classe Refatorada QuoteViewModel 33 1. using System; 2. using QuoteOMatic.Dominio; 3. namespace QuoteOMatic.Servicos.ViewModels 4. { 5. public class QuoteViewModel 6. { 7. public QuoteViewModel(Quote quote) 8. { 9. Number = Convert.ToString(quote.Number); 10. Contents = string.format("{0}", quote.contents); 11. AuthorName = quote.author.name.toupper(); 12. Rating = Convert.ToString(quote.Rating); 13. } 14. public string Number { get; private set; } 15. public string Contents { get; private set; } 16. public string AuthorName { get; private set; } 17. public string Rating { get; private set; } 18. } 19.}
34 Criando a Visão Quote/ListarPorAvaliacao.aspx 1. Clique o BDM na pasta Views/Quote. 2. Escolha Add View.
Criando a Visão Quote/ListarPorAvaliacao 35 1. Em View Name, digite Criar. 2. Escolha a opção Create a stringly-typed view. 3. Em View data class, selecione a classe QuoteViewModel. 4. Em ViewContent, selecione List. 5. Clique em Add.
Código da Visão Quote/ListarPorAvaliacao.aspx 36 1. <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 2. Inherits="System.Web.Mvc.ViewPage<IEnumerable<QuoteOMatic.Servicos.ViewModels.QuoteViewModel>>" %> 3. <asp:content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">listarporavalicao</asp:content> 4. <asp:content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 5. <h2>lista de Citações Por Avaliação</h2> 6. <table> 7. <tr><th>number</th><th>contents</th><th>authorname</th><th>rating</th></tr> 8. <% foreach (var item in Model) { %> 9. <tr> 10.<td><%= Html.Encode(item.Number) %></td> 11.<td><%= Html.Encode(item.Contents) %></td> 12.<td><%= Html.Encode(item.AuthorName) %></td> 13.<td><%= Html.Encode(item.Rating) %></td> 14.</tr> 15.<% } %> 16.</table> 17.<p><%= Html.ActionLink("Criar Citação", "Criar") %></p> 18.</asp:Content>
A Classe Refatorada QuoteService 37 1.... 2. namespace QuoteOMatic.Servicos 3. { 4. public class QuoteService 5. { 6.... 7. public IEnumerable<QuoteViewModel> ReturnListByRating() 8. { 9. var result = new List<QuoteViewModel>(); 10. var quotes = _quoterepository.findall(); 11. foreach (var quote in quotes) 12. { 13. result.add(new QuoteViewModel(quote)); 14. } 15. return result.orderbydescending(quote => quote.rating); 16. } 17. } 18.}
A Classe Refatorada QuoteController 38 1.... 2. namespace QuoteOMatic.Controladores 3. { 4. public class QuoteController : Controller 5. { 6.... 7. [HttpGet] 8. public ActionResult ListarPorAvaliacao() 9. { 10. return View(_quoteService.ReturnListByRating()); 11. } 12. } 13.}
Experimento 4 39 Refatore a classe QuoteViewModel para incluir as propriedades Number e Rating. Crie a visão Quote/ListarPorAvalicao.aspx fortemente tipada ao QuoteViewModel. Refatore a classe QuoteController para incluir a ação ListarPorAvaliacao. Refatore a classe QuoteServices para incluir o método ReturnListByRating. Liste as citações criadas digitando http://localhost:3777/quote/listarporavaliacao. Lembre-se que essa URL muda a cada execução da aplicação. Teste a aplicação. Ela deverá continuar funcionando.