quinta-feira, 24 de maio de 2012
Pequeno Tutorial de LINQ
O Linq traz uma forma de tratar o banco de dadosque me agradou muito, que foi a portabilidade, quantas vezes eu tive que sair caçando SQLs que pararam de funcionar porque saiu do Access pro MySql ou do MySql pro SqlServer e ate mesmo pro Oracle?
Com o Linq acabou isso tudo, e a forma que ele trata as queries torna a coisa mais facil para se programar, o Visual Studio integra todo mundo perfeitamente, e com pouca coisa ja se sai programando normalmente conseguindo uma produção normal em qualquer cenario de trabalho.
Inicialmente devemos instanciar o banco de dados na classe que sera criado a querie Linq, Vou dar como exemplo a forma que eu instancio, lembrando que nesse exemplo eu estou usando o Linq to Entities
[Atualização = Observação muito bem vinda do Bernardo do grupo .Net-Br usar o using ao invez de declarar direto como eu fiz, faz que o dispose seja automatico]
using BancoEntities BD = new BancoEntities();
Caso nao saiba fazer uma conexao de exemplo, aqui mesmo no blog eu ja postei sobre como fazer uma conexão com o MySql
Num banco de dados de exemplo poderiamos colocar as tabelas:
TbFuncionarios
FuncId - Int - Pk
FuncNom - VarChar - 50 Caracteres
FuncEnd - VarChar - 100 Caracteres
TbHorarios
HorId - Int - Pk
FuncId - Int - Fk
HorManha - Hora
HorTarde - Hora
HorDat - Data
Não vou me ater muito a modelagem porque esse não é o proposito do post, e para o aprendizado essas duas tabelas ja estao bem, veja que temos um relacionamento de um para muitos (um funcionario muitos horarios)
Vamos Iniciar com um select simples na tabela de funcionarios
Sql => Select FuncId, FuncNom, FuncEnd from tbFuncionarios
Linq => from Listagem in BD.tbFuncionarios select new {Listagem.FuncId, Listagem.FuncNom, Listagem.FuncEnd}
Sql => Select * from tbFuncionarios
Linq => from Listagem in BD.tbFuncionarios select Listagem
lembrando que usar o * em SQLs prejudica a performance porque o comando tem que ir na tabela central do banco de dados achar quem sao todos os campos da tabela em questao para so depois dar select nelas, ja no Linq isso nao ocorre porque ele ja tem a referencia pelo Entities.
ja um select com where:
Sql=> Select FuncId, FuncNom, FuncEnd from tbFuncionarios where FuncNom = 'XXX'
Linq=> from Listagem in BD.tbFuncionarios where Listagem.FuncNom == 'XXX' select new {Listagem.FuncId, Listagem.FuncNom, Listagem.FuncEnd}
Por estarmos lidando com uma linguagem tipada é bom não esquecer de que as comparações do where sao obrigatoriamente do mesmo tipo ou seja string == string, int==int, e assim por diante, frisando bem CHAR NAO É IGUAL VARCHAR, INT NAO É IGUAL A DOUBLE
Mas nao estamos a beira do precipicio nesse sentido, porque vc pode usar os casts ou seja o .ToString() e assim por diante, o importante é que na comparação final os tipos estejam devidamente igualados, senão nao funciona
e que tal com o order by?
SQL=> Select FuncId, FuncNom, FuncEnd from tbFuncionarios order by FuncNom
Linq=>from Listagem in BD.tbFuncionarios order by Listagem.FuncNom select new {Listagem.FuncId, Listagem.FuncNom, Listagem.FuncEnd}
agora algo que revirei por horas por algo entendivel na net e nao achei, e muita mas muita gente mesmo tem essa duvida que é o famoso inner join
SQL=> Select FuncId, FuncNom, FuncEnd, tbHorarios.HorManha from tbFuncionarios inner join tbHorarios on tbHorarios.FuncId = Funcionarios.FuncId order by FuncNom
Linq=> from Listagem in BD.tbFuncionarios
join ListaHoras in BD.tbHorario on Listagem.FuncId equals ListaHoras.FuncId
select new {Listagem.FuncId, Listagem.FuncNom, Listagem.FuncEnd, ListaHoras.HorManha}
Lembrando mais uma vez que deve se igualar os tipos.
Espero ter ajudado
Ate mais!
quarta-feira, 23 de maio de 2012
Gerando uma Grid com a WebGrid
O WebGrid é um helper completo para grids, fornecendo paginação de varios tipos, de forma facil e rapida, organização (sort) em qualquer coluna, e isso tudo sem a menor complicação.
E caso o visual simples nao agrade ou nao seja exatamente o necessario no sentido de visualização, ainda assim vale a pena utilizar esse helper, ja que existem grids que se adaptam a qualquer <table> com zero de configuração.
Segue o codigo:
WebGrid Grid = new WebGrid(ViewBag.Listagem,selectionFieldName: "SelectedRow", rowsPerPage:10,canPage:true); @Grid.GetHtml( columns: Grid.Columns( Grid.Column("Nome_Cidade", "Cidade", format: (item) => HttpUtility.HtmlDecode(item.Nome_Cidade)), Grid.Column("Nome_Estado","Estado", format: (item) => HttpUtility.HtmlDecode(item.Nome_Estado)), Grid.Column("Grupo_Nome","Nome do Grupo", format: (item) => HttpUtility.HtmlDecode(item.Grupo_Nome)), Grid.Column("NUsuarios","Usuarios neste Grupo"), Grid.Column("", header: "Ações", format: (item) => new HtmlString( Html.ActionLink("Editar", "EditGrupo", new { id = item.GrupoId }).ToString() " | " Html.ActionLink("Deletar", "DelGrupo", new { id = item.Usu_Gru_Cod }).ToString() ) ) ), firstText:"Primeiro", previousText:"Anterior", nextText:"Proximo", lastText:"Ultimo", mode:WebGridPagerModes.All )Aqui eu coloquei uma consulta linq na ViewBag.Listagem que contem os campos Nome_Cidade, Nome_Estado, Grupo_Nome, e uma contagem de quantos usuários estao em cada grupo, NUsuarios Em Grid.Columns, iniciei a configuração das colunas e a linkagem.
Aqui vale uma observação:
format: (item) => HttpUtility.HtmlDecode(item.Grupo_Nome)
acontece de as vezes pegarmos strings com o formato de html, mudando os acentos dai nao reconhece na programação. O HttpUtility.HtmlDecode serve exatamente para isso. Procurei muito ate achar alguma referencia a isso.
e por fim temos o
Grid.Column("", header: "Ações", format: (item) => new HtmlString(Html.ActionLink("Editar", "EditGrupo", new { id = item.GrupoId }).ToString() " | " Html.ActionLink("Deletar", "DelGrupo", new { id = item.GrupoId }).ToString())
Aqui é a coluna que eu coloquei os botões de ação para poder alterar cada registro separadamente
e por fim
firstText:"Primeiro", previousText:"Anterior", nextText:"Proximo", lastText:"Ultimo", mode:WebGridPagerModes.All
firstText => texto do link que leva ao primeira página
previousText => texto do link que leva a página anterior
nextText => texto do link que leva a proxima página
lastText => texto do link que leva a ultima página
mode => o modo de mostragem dos links de paginação
nesse exemplo foi feita uma paginação de 10 registros por página
e caso o proprio helper nao tenha sido o suficiente para ser usado devido a simplicidade ainda existem grids em jquery que deixam a grid estilizada com zero de configuração como a Flexigrid que basta adicionar o seguinte java:
$('.Grid').flexigrid();onde .Grid é a classe da WebGrid.
Espero ter ajudado.
Ate a proxima!
segunda-feira, 21 de maio de 2012
Gerando uma grid agrupada com Ext JS
Hoje vou postar sobre como gerar uma grid com registros agrupados, e botões de ação.
Inicialmente quero frisar que o framework Ext Js é pago, sendo liberado apenas para projetos open source, porem o custo x beneficio dele é muito bom mesmo.
Primeiro baixem o framework no site Sencha.
Uma vez salvo no computador local, vamos instala-lo:
Por motivos de organização eu optei por colocar os .js na pasta Content > Ext, e as imagens em resources > images como mostra na figura abaixo
Na pasta Ext tem todos os arquivos java do framework enquanto na images tem as imagens do framework.
Abra um projeto de nome de sua preferencia e vamos instalar o framework nele.
<link rel="stylesheet" href="@Url.Content("~/Content/ext/css/ext-all.css")" type="text/css" media="screen" />
<script type="text/javascript" src="@Url.Content("~/Content/ext/js/ext-all.js")"></script>
Aqui existem algumas observações:
Em muitos exemplos pela internet afora eu vejo as pessoas referenciando seus arquivos de forma manual, eu nao vejo isso como certo, porem eu gosto de desenvolver localmente e fazer o deploy de arquivos apenas quando necessario mesmo, entao nesse caso, para poder ter mais produtividade eu uso o "URL.Content" que "descobre" a estrutura de pasta que se encontra e ja a usa de forma correta.
Voltando ao sssunto principal, basta referenciarmos esses dois arquivos que o framework ja estara instalado.
No Mvc, o correto é gerar models "gordas", com todo o processamento entao em uma interface eu criei um content result como se segue:
public ContentResult XmlUsuariosGrupos(string Conf)
{
BancoEntities BD = new BancoEntities();
//reconstruindo o helper para dar o action no link-------------------------------------------------------------------------------
HttpContextWrapper httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, RouteTable.Routes.GetRouteData(httpContextWrapper)));
//-------------------------------------------------------------------------------------------------------------------------------
var Listagem = (from usu_grupos in BD.usu_grupos
from usuarios in BD.usuarios
where
usuarios.CodGrupo == usu_grupos.Usu_Gru_Cod &&
usu_grupos.Conf_Codigo == Conf
select new
{
usu_grupos.Usu_Gru_Nome,
usuarios.Nome,
usuarios.Sobrenome,
usuarios.CodUsuario,
usuarios.CodGrupo
});
XElement matches = new XElement("Grupos");
XElement match = null;
XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), matches);
foreach (var item in Listagem)
{
match = new XElement("Agrupamento");
match.Add(new XElement("id", item.CodUsuario));
match.Add(new XElement("Nome", item.Nome + " " + item.Sobrenome));
match.Add(new XElement("Grupo", item.Usu_Gru_Nome));
match.Add(new XElement("Acoes", "<a href='" + urlHelper.Action("EditaDireitosEspeciais", "Iniciais", new { id = item.CodUsuario, CodGrupo = item.CodGrupo } ) + "'>Gerenciar Direitos Especiais</a>"));
matches.Add(match);
}
ContentResult ret = new ContentResult();
ret.ContentType = "text/xml";
ret.Content = doc.ToString();
return ret;
}
Com isso geramos um xml satisfatorio para o Framework, vamos prestar atenção em um detalhe: no contexto de model o helper do action link nao funciona, sendo que é necessário reconstruir o mesmo dentro do ContentResult para o mesmo poder ser utilizado, afinal por mais utilidade que se tenha uma listagem, ela não passa apenas de uma listagem, e as vezes precisamos de botões de ação, para edição de usuarios, CRUDS em geral, etc.
Na nossa view eu coloquei o java da seguinte forma:
<script type="text/javascript">
Ext.Loader.setConfig({
enabled: true
});
Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
]);
Ext.onReady(function () {
Ext.define('Book', {
extend: 'Ext.data.Model',
fields: [
{name: 'Nome', mapping: 'Nome' },
'Grupo', 'Acoes'
]
});
var store = Ext.create('Ext.data.Store', {
model: 'Book',
autoLoad: true,
//inserindo propriedades de agrupamento------------
groupField: 'Grupo',
//-------------------------------------------------
proxy: {
type: 'ajax',
url: "@Url.Content("~/Listagem/_ListaGruposUsuariosXml/")?Conf=@ViewBag.Conf",
reader: {
type: 'xml',
record: 'Agrupamento',
idProperty: 'id'
}
}
});
var groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
groupHeaderTpl: 'Nome do Grupo: {name} ({rows.length} Usuários Cadastrado{[values.rows.length > 1 ? "s" : ""]})',
hideGroupedHeader: false,
startCollapsed: true
});
// create the grid
var grid = Ext.create('Ext.grid.Panel', {
store: store,
columns: [
{ text: "Nome", width: 250, dataIndex: 'Nome', sortable: true },
{ text: "Nome do Grupo de usuários", width: 250, dataIndex: 'Grupo', sortable: true },
{ text: "Ações Possiveis", width: 250, dataIndex: 'Acoes', sortable: false },
],
//funcoes extras---------------------------------------------------------------------
collapsible: true,
animCollapse: true,
iconCls: 'icon-grid',
frame: true,
resizable: true,
title: "Grupos de usuários",
//----------------------------------------------------------------------------------
//aqui começa o agrupamento----------------------------------------------------------
features: [groupingFeature],
//-----------------------------------------------------------------------------------
renderTo: 'Grid',
width: 900,
height: 700
});
});
</script>
Bom primeiramente, devo me desculpar pois eu fiz muito "em cima do exemplo" do site do Ext JS, detesto manter os nomes das variaveis, mas como o proposito aqui é apenas um exemplo entao acabei deixando.
Alguns detalhes merecem um pouco de atenção como a linha:
Ext.Loader.setPath('Ext.ux', '../ux');
Aqui o framework diz onde estao seus outros arquivos de apoio e o motivo que eu deixei a organização dele sem mexer, apenas para melhorar a compreensão.
na linha
url: "@Url.Content("~/Listagem/_ListaGruposUsuariosXml/")?Conf=@ViewBag.Conf",
chamamos o ajax que carregara a grid com o xml de dados, observe o uso do helper Url.Content .
o Xml que eu gerei ficou mais ou menos assim
<Grupos> <Agrupamento> <id>77</id> <Nome>Theo Teste</Nome> <Grupo>Grupo Limitado</Grupo> <Acoes><a href='/Iniciais/EditaDireitos/77?Grupo=139'>Gerenciar Direitos Especiais</a></Acoes> </Agrupamento> </Grupos>
nas linhas
reader: {
type: 'xml',
record: 'Agrupamento',
idProperty: 'id'
}
Indicamos que sera enviado um xml, ja que o framework suporta outros formatos, informamos que as linhas estao na chave Agrupamento, e o Id de cada registro é o id
nas linhas:
Ext.onReady(function () {
Ext.define('Book', {
extend: 'Ext.data.Model',
fields: [
{name: 'Nome', mapping: 'Nome' },
'Grupo', 'Acoes'
]
Definimos o nome das colunas, preste atenção que somente a primeira precisa ser mapeada, sendo que as outras ja vem na sequencia apenas com os nomes
nas linhas:
var groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
groupHeaderTpl: 'Nome do Grupo: {name} ({rows.length} Usuários Cadastrados{[values.rows.length > 1 ? "s" : ""]})',
hideGroupedHeader: false,
startCollapsed: true
});
criamos a grid com o agrupamento sendo que antes do nome do agrupamento vira a string "Nome do Grupo:" e o proprio framework faz a conta de linhas em
({rows.length} Usuários Cadastrados{[values.rows.length > 1 ? "s" : ""]})
para saber quantos usuarios estao cadastrados nesse agrupamento.
na linha:
startCollapsed: true
diz que os registros ja vem "fechados" mostrando apenas os agrupamentos.
nas linhas:
var grid = Ext.create('Ext.grid.Panel', {
store: store,
columns: [
{ text: "Nome", width: 250, dataIndex: 'Nome', sortable: true },
{ text: "Nome do Grupo de usuários", width: 250, dataIndex: 'Grupo', sortable: true },
{ text: "Ações Possiveis", width: 250, dataIndex: 'Acoes', sortable: false },
],
Informamos o framework que a chave "Nome" no Xml linka com a Coluna "Nome", sua largura em px, e se ele pode ser "organizavel" ou seja se vc pode clicar na coluna e a grid se rearranjar em ordem crescente ou decrescente com base na coluna selecionada, as outras linhas seguem o mesmo padrão.
nas linhas:
//funcoes extras---------------------------------------------------------------------
collapsible: true,
animCollapse: true,
iconCls: 'icon-grid',
frame: true,
resizable: true,
title: "Grupos de usuários",
//----------------------------------------------------------------------------------
temos as funções extras da grid, autoexplicaveis.
na linha:
//aqui começa o agrupamento----------------------------------------------------------
features: [groupingFeature],
//-----------------------------------------------------------------------------------
aplicamos as preferencias ja citadas na grid
nas linhas:
renderTo: 'Grid',
width: 900,
height: 700
informamos que o elemento que recebera a grid tem o Id de "Grid", sua largura e altura, no meu caso foi uma div com id de "Grid"
espero ter sido de utilidade, e em caso de duvidas ou afins, por favor me enviem um email ou comentem a duvida porque eu ficarei feliz em ajudar...
sexta-feira, 18 de maio de 2012
Conectando o MySql no Visual Studio 2010
Primeiro vamos as considerações:
Nao adianta querer trabalhar com o MySql no Visual Studio 2010 express, ele simplesmente nao tem suporte.
(Mas como assim? eu conheço fulano, ciclano e beltrano que conseguiu) Explicando, ele nao tem um suporte facil, porem se voce ja dominar a linguagem você consegue sim (todo o segredo esta no web.config), porem com muitas limitações(code first pode esquecer).
O melhor suporte que eu encontrei foi no Visual Studio 2010 ultimate que é o que eu vou descrever aqui.
Me parece, não sei se estou certo, a Microsoft não tem interesse em tornar o MySql nativo do Visual Studio, nao sei se no 2011 ja mudou, mas acredito que não.
Entao temos que baixar o conector do MySql, nao vou colocar o link direto aqui, esse foi um erro que encontrei em diversos sites que eu consultei inicialmente para tentar entender e sempre ficava a duvida se as instruções eram para uma versão especifica ou era mais generico, basta entrar no site do MySql, e baixar a ultima versão do conector que sempre sera necessario, por diversos motivos, entre eles, correção de bugs, mais rendimento e etc...
Uma vez baixado e instalado, reinicie o Visual Studio e mãos a obra.
Modele o banco de dados externamente já que o code first não esta disponivel (se alguem conseguiu comente que eu estudo o modo e coloco um post so sobre isso aqui), e no projeto criado clique com o botao direito na pasta models(para uma melhor organização) selecione "Add" e na aba seguinte "New Item" ira aparecer uma janela mais ou menos como a da imagem abaixo, basta selecionar em "Installed Templates" a opção "Data" para filtrar as opções de dados e logo após "ADO.NET Entity Data Model", como na imagem abaixo:
Quando clicar em ok uma janela como a de baixo ira aparecer:
Escolha o "Generate from database", pois o outro gera um sql que não é inteiramente compativel com o MySql, pelo menos ate a versão que eu testei, entao recomendo usar ele
Clicando em "Next" a proxima tela ira aparecer:
Eu numerei os passos, no circundado numero 1 voce podera escolher entre outras conexoes ja prontas entre todos os bancos de dados que ja foram selecionado, aqui iremos escolher "New Connection"
Ira aparecer uma tela como a seguir:
sexta-feira, 11 de maio de 2012
Autenticação Basica - Macete
No MVC isso tudo mudou para que a autenticação fique ativa num controller inteiro basta que decoremos o controller com [Authorize] como mostra a imagem abaixo:
Essa decoração faz com que o framework va ate seu arquivo Web.Config que fica na raiz do projeto (lembrando que tem outro na raiz da pasta views) , verificar o modo de autenticação que será usado no projeto, temos as opções:
Forms: Você mesmo constroi um form que coleta informações do usuario e a autentica
None: todos tem acesso livre e irrestrito na aplicação
Passport: Utiliza o sistema passport da microsoft no qual basta que se tenha um email cadastrado na base da microsoft para que se tenha acesso a aplicação.
Windows: Usuarios autenticados no windows tem acesso a aplicação (por exemplo em uma rede corporativa
Em outros posts irei detalhar as outras opções, mas nesse irei falar um pouco da minha experiencoa com a opção forms.
No arquivo Web.Config da raiz da aplicação teremos um trecho de codigo parecida com:
<authentication mode="Forms"> <forms loginUrl="~/Login/Index" /> </authentication>
aqui diz que o motedo que sera usado é o forms e que a action que sera usada para a autenticação esta no controller login e na action index.
Uma coisa que me impressionou muito com esse metodo de autenticação foi que a pessoa ao tentar acessar uma url protegida, ela é encaminhada para a url de autenticação, e depois de um login bem sucedido, a mesma retorna para a pagina que tentou acessar, tudo isso com pouca programação, ja que o framework armazena a pagina que o usuario tentou acessar na variavel ReturnUrl.
Porem o macete é que num controller comum que se tem a mesma action sobrecarregada com metodos diferentes essa variavel sempre fica acessivel na action inicial do projeto como mostra a figura abaixo:
Essa variavel tem que ser corretamente tratada pois pode ser que o usuario acesse o sistema atraves de sua pagina de login, e nesse caso a variavel ficara vazia, porem ela sera mostrada na barra dew endereços do navegador (ja que ela é uma query string) porem ao se clicar em login a mesma sera ignorada gerando confusão.
Esse metodo de autenticação so funciona com o SetAuthCookie que tera o valor que sera usado para futuras validações, como mostra o trecho de codigo abaixo.
Aqui para fins de exemplo, eu coloquei uma string fixa como informação, mas podera ser colocado qualquer coisa, como o id do usuário e afins.
System.Web.Security.FormsAuthentication.SetAuthCookie("Blog do Theo Alexandre Miliani", false);
Não adianta colocar outros tipos de cookies, pois o framework so reconhece esse cookie como autenticação.
Aqui vemos que o mesmo esta no namespace "System.Web.Security".
Entre aspas está a variavel a ser checada no caso "Blog do Theo Alexandre Miliani" e depois da viirgula fica a referencia se o cookie deve ser persistente (continuar valido mesmo apos fechar o navegador) ou não e aqui esta como não.
E para "Deslogar" do sistema basta uma linha:
System.Web.Security.FormsAuthentication.SignOut();
Espero ter ajudado.
Ate a proxima!
quarta-feira, 9 de maio de 2012
Salvar arquivos em C#
Não estou falando mau da linguagem, mesmo porque ela é muito antiga e foi abandonada, entao para a epoca que foi concebida, era excelente.
Porem hoje em dia com o C# a coisa fica absurdamente facil, quando eu fiz meu primeiro upload nao achei fontes relativamente faceis para eu poder entender completamente logo na primeira vez, entao quero postar algo que eu acredito seja muito facil entender e tambem, acaba sendo uma classe facil de portar para qquer projeto.
No sistema em questao eu precisava gerar um nome unico pro arquivo salvo (acho que esse requisito é necessário na maioria das vezes)
Para tanto eu crio a classe que utiliza HttpPostedFileBase (mais informações aqui)
O System.DateTimeOffset.Now.Ticks calcula quantos segundos existiram desde 01/01/1900 entao desde que os segundos so se acumulam, acaba sendo na minha opinião um valor unico para nome de arquivo, mesmo que existem dois uploads simultaneos nao consigo ver como eles seriam feitos exatamente no mesmo segundo, e para melhorar mais o nome original do arquivo, tbm é salvo, entao a possibilidade de dois arquivos exatamente com o mesmo nome é quase nula, em outro post colocarei como obter isso de outras formas
mais informações sobre o System.DateTimeOffset.Now.Ticks aqui
aqui esta o codigo:
public string SalvaArquivo(HttpPostedFileBase Postado, string Caminho)
{
string NomeArquivo = System.DateTimeOffset.Now.Ticks.ToString() + Path.GetFileName(Postado.FileName);
Postado.SaveAs(Caminho + NomeArquivo);
return NomeArquivo.ToString();
}
Espero ter ajudado...
segunda-feira, 7 de maio de 2012
Bulk Inserts em C#
A forma com o SQL classico e a forma com o linq.
Nesse exemplo existe tbm a necessidade de se apagar os registros anteriores para se inserir registros novos.
Eu pessoalmente acredito que a forma de deleção com o linq poderia ser melhorada, ja que para se deletar diversos registros de uma unica vez, fica necessaria um select e um loop com delete de objeto por objeto de registro, enquanto no sql tradicional basta apenas um unico delete ficando o resto do processamento dele para o proprio banco de dados (se alguem souber de alguma forma melhor de se fazer isso sem o loop fique a vontade para dizer).
Como se ve nos codigos:
Com Linq:
int CodUsuario = Convert.ToInt32(Formulario["CodUsuario"]);
var Deleta = from ObjDeleta in BD.tblAlvo where ObjDeleta.CodUsuario == CodUsuario select ObjDeleta;
foreach (var del in Deleta)
{
BD.tblAlvo.DeleteObject(del);
}
BD.SaveChanges();
Com Sql normal
DB.ExecuteStoreCommand("delete from tblAlvo where CodUsuario= " + CodUsuario + "");
Já na inserção nao existe nenhuma grande novidade, exceto que com o linq me pareceu muito mais seguro devido as regras inseridas no entities, enquanto no sql normal a inserção fica vulneravel ao sql injection
Nesse sistema foi inserido um drag'n'drop na tela que o usuario tem acesso para modificar os direitos de acesso para usuarios, que altera um hiddem atraves de jquery, criando uma array Ex. 1,4,7,9,10
com Linq
int CodUsuario = Convert.ToInt32(Formulario["CodUsuario"]);
Array Menu = Formulario["MenuEspecial"].Split(',');
foreach (var item in Menu)
{
var Menus = new tblAlvo();
Menus.CodUsuario = CodUsuario;
Menus.Menu_Cod = Convert.ToInt32(item);
BD.tblAlvo.AddObject(Menus);
BD.SaveChanges();
}
com Sql Normal
int CodUsuario = Convert.ToInt32(Formulario["CodUsuario"]);
Array Menu = Formulario["MenuEspecial"].Split(',');
foreach (var item in Menu)
{
DB.ExecuteStoreCommand("insert into tblAlvo (CodUsuario, Menu_Cod (values "+CodUsuario+","+ item +");
}
Embora com menos codificação no modo SQL, o mesmo fica mais exposto a ataques de inserções maliciosas.
Espero ter ajudado
Ate mais...
domingo, 6 de maio de 2012
Função do Controller
Eu vejo muito por aí as pessoas colocando muitas funções no controller e eu mesmo até um tempo atrás colocava muito processamento num controller, porém um amigo da lista .Net-Br me indicou uma forma melhor para organizar o código, e hoje em dia percebo as vantagens dessa organização.
No modelo MVC de programação o controller é responsável pelo direcionamento de actions, rotas, pedido de processamento para as models, e pouco processamento efetivo, tais como um try catch ou talvez um if, mas o processamento mais pesado fica em interfaces, nas models mais dedicadas a isso, note que não estou dizendo que deveria ficar na mesma models que trata do banco de dados mas numa em separado, possibilitando que determinadas classes sejam inclusive reutilizados em outros setores do sistema em desenvolvimento, eu pessoalmente crio uma pasta com o nome do controller que ela será utilizada, sem a extensão controller, claro.
Na próxima postagem, pretendo colocar alguns exemplos dessa organização.
Até mais...
sábado, 5 de maio de 2012
Visual Studio 2010 Intelisense
Excelente ferramenta de trabalho, pessoalmente acho que esta entre as melhores.
Porem existe um pequeno macete que as vezes eu preciso prestar atenção, o intelisense, quando se insere um input simples, ele traz a sugestao do codigo, quando aceita ele ja insere o codigo todo porem com algo a MENOS, o "name", sempre tem que prestar atenção nisso porque ja me levou algumas horas sem saber porque nao trazia os dados postados.
Dando o pontapé inicial!
Sejam Bem vindos ao meu Blog pessoal.
Aqui pretendo postar coisas do meu dia a dia sobre programação, macetes e afins que eu nao encontro muito facil pela internet a fora.
Gosto de pensar que estarei contribuindo de alguma forma para que outros programadores sejam beneficiados de alguma forma com minhas postagens...
Ate mais pessoal!