ASP .NET MVC 3 - Criando uma aplicação ASP .NET MVC - I
Este artigo é baseado no original: Creating an Entity Framework Data Model for an ASP.NET MVC Application (1 of 10) com adaptações e pequenos ajustes feitos por mim.
Nosso objetivo é criar uma aplicação ASP .NET MVC usando o Entity Framework e a nova tecnologia ASP .NET MVC3.
Alguns
novos recurso da ASP .NET MVC 3: - A ASP .NET MVC 3 é compatível com a ASP.NET MVC 2 - o que significa que será fácil atualizar os projetos que você está escrevendo com a MVC 2 para a MVC 3; - A ASP .NET MVC 3 pode ser instalada lado-a-lado com a ASP.NET MVC 2; - A ASP .NET MVC 3 apresenta um novo conjunto de templates de projeto; - A ASP .NET MVC 3 inclui um conjunto de melhorias específicas para a View; A janela Add-> View permite escolher a sintaxe que você deseja usar ao criar novos arquivos de modelos de visão; - A ASP .NET MVC 3 permite usar o novo recurso Razor; - A ASP .NET MVC 3 inclui vários aperfeiçoamentos específicos para o controlador; - A ASP .NET MVC 3 incrementa a API ViewData com uma nova propriedade "ViewModel" no Controlador que é do tipo "dynamic" - e que permite que você use o novo suporte à linguagem dinâmica dentro de VB e C#; - A ASP .NET MVC 3 inclui vários tipos de novos ActionResult e seus métodos de ajuda correspondentes. - A ASP .NET MVC 3 inclui suporte para ligação de dados JSON; - A ASP .NET MVC 3 incrementa o modelo de validação, e adiciona suporte para vários dos novos recursos de validação introduzidos dentro do namespace System.ComponentModel.DataAnnotations do .NET 4. - A ASP .NET MVC 3 oferece um melhor suporte para aplicação de injeção de dependência (DI) e integração com containers de injeção de dependência/IOC; |
Iremos criar uma aplicação ASP .NET para uma faculdade que inclui funcionalidades como matricular estudantes, criar cursos e realizar as atribuições dos instrutores.
Estarei usando o Visual Web Developer 2010 Express edition para criar o projeto que vai mostrar como usar o Entity Framework além dos seguintes tópicos:
•
Criação de
um modelo
de
dados
usando
atributos
e anotações
de
dados
e
a API
fluente
para
o
mapeamento
do banco de
dados.
•
Realizar
operações
básicas CRUD.
•
filtragem,
ordenação
e
agrupamento
de dados.
• Trabalhar
com
dados
relacionados.
•
Tratamento
de
simultaneidade.
•
Implementação de
tabela
por
hierarquia
de
herança.
•
Implementar
o
repositório
e
unidade
de
padrões de
trabalho.
•
Realizar
consultas
SQL.
• Trabalhar
com
classes
proxy.
• Detecção
de
desativação
automática
de mudanças.
• Validação
de
desativação,
quando
salvar as
alterações
Antes de iniciar verificar se você possui os seguintes recursos instalados:
Criando o projeto ASP .NET MVC
Abra o Visual Web Developer 2010 Express Edition e no menu File clique em New Project; a seguir selecione o template para a linguagem Visual Basic -> Web e a seguir o modelo ASP .NET MVC 3 Web Application, informe o nome UniversidadeMacoratti e clique em OK;
A seguir selecione a opção Internet Application, como View Engine o Razor e desmarque a opção Create Unit Test Project e clique em OK;
Obs: Na verdade a opção Create Unit Test Project só esta habilitada no Visual Studio 2010.
Será criado um projeto que pode ser visto na janela Solution Explorer com a seguinte estrutura:
Definindo o estilo do site
Vamos fazer algumas mudanças simples para criar o menu do site, o leiaute e a
home page.
A fim de configurar o menu, no arquivo Views\Shared\_Layout.vbhtml
substitua o texto do cabeçalho existente e os links do menus como mostrado na
figura abaixo:
Agora abra o arquivo Views\Home\Index.vbhtml e remova tudo após a tag de cabeçalho <h2>;
A seguir abra o arquivo Controllers\HomeController.vb e substitua "Welcome to ASP.NET MVC!" por "Bem Vindo a Universidade Macoratti". (ou outro texto de sua preferência)
No arquivo Content\Site.css vamos realizar as seguintes alterações afim de mover as tabs do menu para a esquerda:
#main
{
clear : both;
padding: 30px 30px 15px 30px;
background-color: #fff;
border-radius: 4px 0 0 0;
-webkit-border-radius: 4px 0 0 0;
-moz-border-radius: 4px 0 0 0;
}
nav
,#menucontainer
{margin-top: 40px;
clear: both;
float: left;
}
Execute o projeto e verifique se a página principal exibe o menu conforme a figura abaixo:
Criando o Data Model
Em seguida, vamos criar as classes das nossas entidades da nossa aplicação.Vamos iniciar definindo as seguintes entidades: Estudante, Curso, Matricula:
Relacionamento um-para-muitos : um registro na Tabela A pode ter muitos registros coincidentes na Tabela B, mas um registro na Tabela B tem um só registro coincidente na Tabela A. O relacionamento é representado pelo sinal: 1:N que expressa a cardinalidade do relacionamento.Obs:Um relacionamento um-para-muitos é criado se apenas uma das colunas relacionadas é uma chave primária ou tem uma restrição de exclusividade. A cardinalidade é um conceito
importante para ajudar a definir o relacionamento, ela define o número de
ocorrências em um relacionamento. Um Setor possui quantos empregados?
R: no mínimo 1 e no máximo N. |
Dessa forma um estudante pode estar matriculado em qualquer número de cursos e um curso pode ter qualquer número de estudantes matriculados.
Vamos agora criar classes que representam as nossas entidades;
As classes são criadas na pasta Models clicando com o botão direito sobre a pasta, selecionando Add -> Class e a seguir informando o nome da classe. Vamos iniciar criando o arquivo Estudante.vb e nele vamos definir a classe Estudante conforme abaixo:
A entidade Estudante - Classe Estudante
Imports System.Collections.Generic Namespace UniversidadeMacoratti.Models Public Class Estudante Public Property EstudanteID() As Integer Get Return _estudanteID End Get Set(value As Integer) _estudanteID = value End Set End Property Private _estudanteID As Integer Public Property SobreNome() As String Get Return _sobrenome End Get Set(value As String) _sobrenome = value End Set End Property Private _sobrenome As String Public Property Nome() As String Get Return _nome End Get Set(value As String) _nome = value End Set End Property Private _nome As String Public Property DataMatricula() As DateTime Get Return _datamatricula End Get Set(value As DateTime) _datamatricula = value End Set End Property Private _datamatricula As DateTime Public Overridable Property Matriculas() As ICollection(Of Matricula) Get Return _matriculas End Get Set(value As ICollection(Of Matricula)) _matriculas = value End Set End Property Private _matriculas As ICollection(Of Matricula) End Class End Namespace |
Estou usando a
notação antiga para definir as propriedades mas poderíamos usar as
propriedades auto-implementadas do VB .NET: Para o nosso exemplo teríamos o seguinte: Public Property EstudanteID as
Integer Muito mais simples não é mesmo ???
|
A propriedade EstudanteID será a coluna de chave primária da tabela de banco de dados que corresponde a essa classe. Por padrão, o Entity Framework interpreta uma propriedade que é chamada de ID ou nome_classeID como sendo a chave primária.(podemos alterar esse comportamento com annotations)
A propriedade de Matricula é uma propriedade de navegação. As Propriedades
de navegação tratam outras entidades que estão relacionadas com esta
entidade permitindo que acessemos propriedades relacionadas.
Neste caso, a propriedade Matriculas da entidade Estudante irá
tratar todas as entidades Matricula que estão relacionadas com essa
entidade Estudante.
Ou seja , se uma linha de Estudante na base de dados possuir duas linhas
Matricula relacionadas a propriedades de navegação Matriculas da entidade
Estudante irá conter as duas entidades Matricula.
As propriedades de navegação são tipicamente definidas como virtual/Overridable (sintaxe VB .NET : Overridable) para poder tirar proveito do mecanismo de Lazy Loading do Entity Framework.
Lazy Load é o mecanismo utilizado pelos frameworks de persistência para carregar informações sobre demanda. Esse mecanismo torna as entidades mais leves, pois suas associações são carregadas apenas no momento em que o método que disponibiliza o dado associativo é chamado. Assim quando objetos são retornados por uma consulta, os objetos relacionados não são carregados ao mesmo tempo, ao invés, eles são carregados automaticamente quando a propriedade de navegação for acessada. É também conhecido como "lazy loading". |
A entidade Matricula - Classe Matricula
Vamos criar o arquivo Matricula.vb na pasta Models e nele vamos definir a classe Matricula conforme abaixo:
Obs: Nesta classe eu estou usando a sintaxe simplificada das propriedades Auto-Implementadas
Imports System.Collections.Generic Namespace UniversidadeMacoratti.Models Public Class Matricula Public Property MatriculaID As Integer Public Property CursoID As Integer Public Property EstudandeID As Integer Public Property Grau As System.Nullable(Of Decimal) Public Overridable Property Curso As Curso Public Overridable Property Estudante As Estudante End Class End Namespace |
A propriedade Grau na
versão original do artigo possui a seguinte definição : public decimal? Grade { get; set; } O ponto de interrogação após a declaração de tipo decimal indica que a propriedade da classe é anulável; Um Grau que é nulo(null/nothing) é diferente de um Grau zero; O valor null/nothing significa que Grau ainda não foi atribuído enquanto que um Grau zero que um valor zero foi atribuído ao Grau.
Overridable é a sintaxe VB .NET para virtual. O artigo original usa o
modificador virtual na sintaxe : |
A propriedade EstudanteID é uma chave estrangeira, e a propriedade de
navegação correspondente é Estudante.
Uma entidade Matricula esta associada com uma entidade Estudante,
logo a propriedade pode somente tratar uma única entidade Estudante
(ao contrario da propriedade de navegação Estudante.Matriculas que vimos
anteriormente, que podia conter várias entidades Matricula).
A propriedade CursoID é uma chave estrangeira, e a propriedade de navegação correspondente é Curso. Uma entidade de Matricula está associada com uma entidade Estudante.
A entidade Curso - Classe Curso
Finalmente vamos criar o arquivo Curso.vb na pasta Models e nele vamos definir a classe Curso conforme abaixo:
Imports System.Collections.Generic Namespace UniversidadeMacoratti.Models Public Class Curso Public Property CursoID As Integer Public Property Titulo As String Public Property Creditos As Integer Public Matriculas As ICollection(Of Matricula) End Class End Namespace |
A propriedade Matricula é uma propriedade de Navegação. Uma entidade Curso pode estar relacionada com qualquer número de entidades Matricula.
Criando o Contexto para o Banco de dados (DataBase Context)
A principal classe que coordena as funcionalidades do Entity Framework para um dado modelo de dados é classe database context.
Essa classe é criada por derivação a partir da classe
System.Data.Entity.DbContext.
No seu código você especifica quais entidades serão incluídas no modelo de dados e pode também customizar certos comportamentos do Entity Framework.
No código deste projeto esta classe será definida como: ContextoEscola.
Vamos criar uma nova pasta no projeto chamada DAL. Para isso no menu Project selecione New Folder e informe o nome DAL para pasta criada.
A seguir clique com o botão direito do mouse sobre a pasta DAL e selecione Add Class e informe o nome ContextoEscola.vb;
A seguir defina o código abaixo na classe ContextoEscola:
Imports System.Collections.Generic Imports System.Data.Entity Imports UniversidadeMacoratti.UniversidadeMacoratti.Models Imports System.Data.Entity.ModelConfiguration.Conventions Namespace UniversidadeMacoratti.Models Public Class ContextoEscola Inherits DbContext Public Property Estudantes() As DbSet(Of Estudante) Get Return _estudantes End Get Set(value As DbSet(Of Estudante)) _estudantes = Value End Set End Property Private _estudantes As DbSet(Of Estudante) Public Property Matriculas() As DbSet(Of Matricula) Get Return _matricula End Get Set(value As DbSet(Of Matricula)) _matricula = Value End Set End Property Private _matricula As DbSet(Of Matricula) Public Property Cursos() As DbSet(Of Curso) Get Return _curso End Get Set(value As DbSet(Of Curso)) _curso = Value End Set End Property Private _curso As DbSet(Of Curso) Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder) modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)() End Sub End Class End Namespace |
Este código cria uma propriedade DbSet para cada conjunto de entidade. Na terminologia do Entity Framework , um conjunto de entidades geralmente corresponde a uma tabela do banco de dados, e uma entidade corresponde a uma linha na tabela.
A declaração no método OnModelCreating impede que os nomes da tabela
fiquem no plural. Se você não fizer isso, as tabelas geradas teriam os
nomes: Estudantes, Cursos e Matriculas, em
vez disso os nomes das tabelas serão: Estudante ,Curso
e Matricula.
Se você não quiser adotar esta regra basta remover o código relacionado.
Definindo a string de conexão
Você não tem que criar uma string de conexão. Se você não criar uma, o Entity Framework criará automaticamente um banco de dados SQL Server Express para você. Neste tutorial, porém, você vai trabalhar com o SQL Server Compact, então você precisa criar uma string de conexão para especificar isso.
Abra o arquivo Web.config do projeto e adicione uma nova string de conexão para a coleção connectionStrings, como mostrado no exemplo a seguir. (Certifique-se de atualizar o arquivo Web.config na pasta raiz do projeto. Há também um arquivo Web.config que está na subpasta Views que você não precisa atualizar.)
<? xml version="1.0"?><!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=152368 --> <configuration> <connectionStrings> <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
....... |
Por padrão, o Entity Framework procura por uma string de conexão com o mesmo nome que a classe de contexto de objeto. A string de conexão que você adicionou especifica um banco de dados SQL Server Compact chamado Escola.sdf localizado na pasta App_Data.
Inicializando o banco de dados com dados para teste
O Entity Framework pode criar automaticamente (ou excluir e recriar)
um banco de dados quando o aplicativo é executado. Você pode especificar
que isto deve ser feito cada vez que sua aplicação é executada ou apenas quando
o modelo está fora de sincronia com o banco de dados existente.
Você também pode escrever uma classe que inclui um método que o
Entity Framework chama automaticamente após a
criação do banco de dados para preenchê-lo com dados de teste. Nesta etapa você
vai especificar que o banco de dados deve ser descartado e recriado sempre que
houver alterações no modelo.
Na pasta DAL que criamos o item anterior crie uma nova classe chamada EscolaInitializer.vb e substitua o código existente pelo código a seguir para que o banco de dados seja criado for preciso e os dados de testes sejam carregados para o novo banco de dados:
Código da classe EscolaInitializer:
Imports System.Collections.Generic Imports System.Linq Imports System.Web Imports System.Data.Entity Imports UniversidadeMacoratti.UniversidadeMacoratti.Models Namespace UniversidadeMacoratti.DAL Public Class EscolaInitializer Inherits DropCreateDatabaseIfModelChanges(Of ContextoEscola) Protected Overrides Sub Seed(context As ContextoEscola) Dim estudantes = New List(Of Estudante)() From { _ New Estudante() With { _ .Nome = "Jose Carlos", _ .SobreNome = "Macoratti", _ .DataMatricula = DateTime.Parse("2005-09-01") _ }, _ New Estudante() With { _ .Nome = "Miriam", _ .SobreNome = "Alonso", _ .DataMatricula = DateTime.Parse("2002-09-01") _ }, _ New Estudante() With { _ .Nome = "Jefferson", _ .SobreNome = "Anand", _ .DataMatricula = DateTime.Parse("2003-09-01") _ }, _ New Estudante() With { _ .Nome = "Janice", _ .SobreNome = "Siqueira", _ .DataMatricula = DateTime.Parse("2002-09-01") _ }, _ New Estudante() With { _ .Nome = "Yan", _ .SobreNome = "Li", _ .DataMatricula = DateTime.Parse("2002-09-01") _ }, _ New Estudante() With { _ .Nome = "Bianca", _ .SobreNome = "Justice", _ .DataMatricula = DateTime.Parse("2001-09-01") _ }, _ New Estudante() With { _ .Nome = "Laura", _ .SobreNome = "Norman", _ .DataMatricula = DateTime.Parse("2003-09-01") _ }, _ New Estudante() With { _ .Nome = "Nino", _ .SobreNome = "Olivetto", _ .DataMatricula = DateTime.Parse("2005-09-01") _ } _ } estudantes.ForEach(Function(s) context.Estudantes.Add(s)) context.SaveChanges() Dim cursos = New List(Of Curso)() From { _ New Curso() With { _ .Titulo = "Quimica", _ .Creditos = 3 _ }, _ New Curso() With { _ .Titulo = "Microeconomia", _ .Creditos = 3 _ }, _ New Curso() With { _ .Titulo = "Macroeconomia", _ .Creditos = 3 _ }, _ New Curso() With { _ .Titulo = "Calculo", _ .Creditos = 4 _ }, _ New Curso() With { _ .Titulo = "Trigonometria", _ .Creditos = 4 _ }, _ New Curso() With { _ .Titulo = "Composicao", _ .Creditos = 3 _ }, _ New Curso() With { _ .Titulo = "Literatura", _ .Creditos = 4 _ } _ } cursos.ForEach(Function(s) context.Cursos.Add(s)) context.SaveChanges() Dim matriculas = New List(Of Matricula)() From { _ New Matricula() With { _ .EstudanteID = 1, _ .CursoID = 1, _ .Grau = 1 _ }, _ New Matricula() With { _ .EstudanteID = 1, _ .CursoID = 2, _ .Grau = 3 _ }, _ New Matricula() With { _ .EstudanteID = 1, _ .CursoID = 3, _ .Grau = 1 _ }, _ New Matricula() With { _ .EstudanteID = 2, _ .CursoID = 4, _ .Grau = 2 _ }, _ New Matricula() With { _ .EstudanteID = 2, _ .CursoID = 5, _ .Grau = 4 _ }, _ New Matricula() With { _ .EstudanteID = 2, _ .CursoID = 6, _ .Grau = 4 _ }, _ New Matricula() With { _ .EstudanteID = 3, _ .CursoID = 1 _ }, _ New Matricula() With { _ .EstudanteID = 4, _ .CursoID = 1 _ }, _ New Matricula() With { _ .EstudanteID = 4, _ .CursoID = 2, _ .Grau = 4 _ }, _ New Matricula() With { _ .EstudanteID = 5, _ .CursoID = 3, _ .Grau = 3 _ }, _ New Matricula() With { _ .EstudanteID = 6, _ .CursoID = 4 _ }, _ New Matricula() With { _ .EstudanteID = 7, _ .CursoID = 5, _ .Grau = 2 _ } _ } matriculas.ForEach(Function(s) context.Matriculas.Add(s)) context.SaveChanges() End Sub End Class End Namespace |
O método de Seed toma o objeto de contexto de banco de dados como um
parâmetro de entrada, e o código no método utiliza o objeto para adicionar
novas entidades no banco de dados. Para cada tipo de entidade, o
código cria uma coleção de novas entidades, adiciona-os à propriedade DbSet
adequada, e salva as alterações para o banco de dados.
Não é necessário chamar o método SaveChanges após cada grupo de
entidades, como foi feito aqui, mas fazer isso o ajuda a localizar a origem de
um problema se uma exceção ocorre quando o código é escrito para o banco de
dados.
Agora faça as seguintes alterações no arquivo Global.asax.vb para rodar o código desta classe e alimentar os dados quando a aplicação iniciar:
1- inclua as seguintes declarações imports:
Imports System.Data.Entity Imports UniversidadeMacoratti.UniversidadeMacoratti.DAL Imports UniversidadeMacoratti.UniversidadeMacoratti.Models |
2- No método Application_Start chame um método do Entity Framework(em destaque) que roda o código para alimentar o banco de dados com dados de teste:
Sub Application_Start()AreaRegistration.RegisterAllAreas() Database.SetInitializer(Of ContextoEscola)(New EscolaInitializer()) RegisterGlobalFilters(GlobalFilters.Filters) RegisterRoutes(RouteTable.Routes) End Sub
|
A aplicação está agora configurada de modo que quando você acessa o banco de dados, pela primeira vez em uma execução, o Entity Framework compara o banco de dados com o modelo (sua classe ContextoEscola ). Se houver uma diferença, a aplicação exclui e recria o banco de dados.
Obs: Lembre-se de desativar este recurso quando for colocar a aplicação em produção
Vamos criar agora uma página Web para exibir os dados e neste processo de solicitação dos dados será disparada automaticamente a criação do banco de dados. Mas antes de fazer isso vamos criar um novo controlador, antes dê um build no projeto para fazer com que o modelo e as classes do contexto estejam disponíveis para o controller MVC scaffoding.
Criando o controlador Estudante
Para criar um controller Estudante clique com o botão direito do mouse sobre a pasta Controllers do projeto selecione Add e clique em Controller;
A seguir na janela Add Controller faça as seleções conforme a figura a seguir:
O controller EstudanteController.vb será criado na pasta Controllers e também será criada uma pasta Estudante contendo os arquivos com extensão .vbhtml que usa os recursos do Razor para realizar as operações de inclusão, exclusão e alteração.
Vamos abrir o arquivo EstudanteController.vb. Observe que foi definida uma variável de classe chamada db como uma nova instância do contexto da aplicação(ContextoEscola): Private db As ContextoEscola = New ContextoEscola
O método Action Index obtém uma lista de
Estudantes a partir da propriedade Estudante da instância do
contexto do banco de dados:
|
Foi gerado também de forma automática um conjunto de views Estudante. Para customizar os cabeçalhos padrões e a ordem da coluna na view index, abra o arquivo Views\Estudante\Index.vbhtml e substitua o código existente pelo seguinte código:
Código do arquivo Index.vbhtml da pasta Views\Estudante:
@ModelType IEnumerable(Of UniversidadeMacoratti.UniversidadeMacoratti.Models.Estudante)
@Code ViewData("Title") = "Estudantes" End Code <h2>Estudantes</h2> <p> @Html.ActionLink("Criar Novo", "Create") </p> <table> <tr> <th> SobreNome </th> <th> Nome </th> <th> Data da Matricula </th> <th></th> </tr> @For Each item In Model Dim currentItem = item @<tr> <td> @Html.DisplayFor(Function(modelItem) currentItem.SobreNome) </td> <td> @Html.DisplayFor(Function(modelItem) currentItem.Nome) </td> <td> @Html.DisplayFor(Function(modelItem) currentItem.DataMatricula) </td> <td> @Html.ActionLink("Editar", "Edit", New With {.id = currentItem.EstudanteID}) | @Html.ActionLink("Detalhes", "Details", New With {.id = currentItem.EstudanteID}) | @Html.ActionLink("Deletar", "Delete", New With {.id = currentItem.EstudanteID}) </td> </tr> Next </table> |
Execute o projeto e na página principal clique na aba Estudante. Você deverá obter a página exibida na figura abaixo:
Após testar o projeto, feche o navegador e faça o seguinte:
Clique duas vezes sobre o arquivo Escola.sdf para abrir o DataBase Explorer e a seguir expanda a pasta Tables para ver as tabelas que foram criadas:
Obs: Se você obter um erro verifique se você tem instalado o Visual Studio 2010 SP1 Tools for SQL Server Compact 4.0.
O banco de dados Escola.sdf exibindo as tabelas:
|
Existe uma tabela para cada entidade mas uma tabela adicional chamada EdmMetadata que é usada pelo Entity Framework para determinar quando o modelo e o banco de dados estão fora de sincronia.
Clique com o botão direito do mouse sobre a tabela Estudante e selecione Show Table Data para ver os dados que foram carregados na tabela pela classe EscolaInitializer.
Tabela Estudante:
A quantidade de código que tivemos que escrever para que o Entity Framework pudesse criar o banco de dados para nós foi mínima por causa do uso das convenções, ou dos pressupostos que o Entity Framework adotou.
Vejamos alguns deles abaixo:
Obs: Você já sabe que as convenções podem ser
substituídos (por exemplo, você especificou que os nomes de tabela não deve ser
pluralizado).
Dessa forma você criou um aplicativo simples que usa o Entity Framework e SQL
Server Compact para armazenar e exibir dados.
Pegue o projeto completo aqui:
UniversidadeMacoratti_1.zip
Aguarde que na continuação vamos mostrar como ajustar e customizar as operações CRUD
(criar, ler, atualizar, excluir) que já foram geradas
Acompanhe a continuação neste link : ASP .NET MVC 3 - Revisando e customizando as funcionalidades CRUD básicas com EF II
"Passará o céu e a terra, mas as minhas palavras jamais passarão." (Mateus 24:35)
Referências: