Regras de Negócio - EF
Bom dúvida que tenho é com relação a criação de regras de negócio com o Entity Framework vou tentar passa-la com um exemplo:
Imagine que tenho um model EDM com as seguintes entidades Cliente e Cidade, onde na minha entidade Cliente tenho os atributos IdCliente, Nome, Endereco, IdCidade (FK) e na minha entidade Cidade tenho os atributos IdCidade, Descricao. Meu EDM esta feito funcionando perfeitamente, então inseri uma classe nova no meu projeto para fazer as regras de negócio utilizando os eventos PARTIAL. Por exemplo:
public partial class Cliente
{
partial void OnNomeCliente(string value)
{
if (value == "")
throw new ApplicationException("Nome do cliente não informado!");
}
}
Até ai tudo bem. Agora vem minha dúvida no caso do IdCidade (FK) como eu faço a validação para as chaves estrangeiras utilizando essa camada de regra de negócio??
Gostaria de centralizar todas as regras de negócio nessa camada, é possível fazer isso?? No caso das chaves estrangeiras não tenho eventos PARTIAL para fazer essa validação.
Aguardo uma resposta o mais breve possível!
Julio
Nefrodata Sistemas
Nefrodata Ltda
Curtidas 0
Melhor post
[devmedia .net]
20/01/2009
Bom Dia Júlio, tudo bem ?
Bom, s olução que eu vejo é o seguinte...
Se você tem uma entidade(tabela) que contém as cidades cadastradas,
você tem uma FK, portanto no diagrama das tabelas você terá essa ligação, só aí o banco já barra a
inclusão de um código de cidade que não existe, e lhe dá mensagem de erro..
Mas para evitar que você tente inserir um código de uma cidade que não existe,
na tela de cadastro de cliente onde você deve informar a cidade, você pode colocar
um drop down listando as cidades cadastradas, o usuário que for fazer o cadastro só terá as cidades pré-cadastradas para informar, caso seu drop down tenha além das cidades a opção "Selecione uma cidade"
você coloca no value dessa opção no dropdown o valor de zero (0) caso seja inteiro o campo na tabela,
então você colocará na sua camada de validação o teste :
public partial class Cliente
{
partial void OnIdCidade(int value)
{
if (value == 0)
throw new ApplicationException("Selecione uma cidade!");
}
} Pelo que entendi, sua dúvida será sanada com essa informações... Aguardo contato ! Abraços Carlos Jr
{
partial void OnIdCidade(int value)
{
if (value == 0)
throw new ApplicationException("Selecione uma cidade!");
}
} Pelo que entendi, sua dúvida será sanada com essa informações... Aguardo contato ! Abraços Carlos Jr
GOSTEI 1
Mais Respostas
Nefrodata Ltda
19/01/2009
Bom dia Carlos!
Entendi sua sugestão para a resolução de minha dúvida porém não entendi como isso seria implementado, veja como esta meu EDM:
Veja que não tenho a propriedade IdCidade na minha entidade Cliente, e nesse caso o EF não gera o evento PARTIAL OnIdCidade. O que tenho que fazer para que esse evento seja criado na classe Cliente?
Aguardo resposta o mais breve possivel.
Julio
Nefrodata Sistemas
GOSTEI 0
[devmedia .net]
19/01/2009
Opa,
Como está criando esse diagrama de classes ? você não terá a propriedade IdCidade nessa modelo, você terá uma propriedade Cidade do tipo Cidade, Orientação Ojeto... Poranto quando instanciar uma classe Cliente, neça você terá : Cliente.Cidade.IdCidade Cliente.Cidade.Descricao mas para inserir um Cliente com uma cidade você deverá fazer Cidade cid = new Cidade(); cid.IdCidade = 1; cid.Descricao = "Belo Horizonte" Cliente cli = new Cliente(); cli.Cidade = cid; cli.Nome = "Carlos"; chama o método de inserir passando a classe cli como parâmetro e irá inserir os dados. Lembrando que para preencher os dados da cidade do cliente, você pega de uma tabela... da base de dados.. sacou !? No aguardo... Abraços Carlos Jr
Como está criando esse diagrama de classes ? você não terá a propriedade IdCidade nessa modelo, você terá uma propriedade Cidade do tipo Cidade, Orientação Ojeto... Poranto quando instanciar uma classe Cliente, neça você terá : Cliente.Cidade.IdCidade Cliente.Cidade.Descricao mas para inserir um Cliente com uma cidade você deverá fazer Cidade cid = new Cidade(); cid.IdCidade = 1; cid.Descricao = "Belo Horizonte" Cliente cli = new Cliente(); cli.Cidade = cid; cli.Nome = "Carlos"; chama o método de inserir passando a classe cli como parâmetro e irá inserir os dados. Lembrando que para preencher os dados da cidade do cliente, você pega de uma tabela... da base de dados.. sacou !? No aguardo... Abraços Carlos Jr
GOSTEI 0
Nefrodata Ltda
19/01/2009
Carlos a inclusão de registros eu faço dessa maneira mesmo, vou te passar um exemplo, porém minha dúvida é como aplicar uma regra de negócio para Cidade na minha camada de regra de negócios, sua sugestão inicial é perfeita porem não consigo implementa-la. Não gostaria de ter uma parte de minha regra de negócio numa camada e a outra parte no cliente.
ModeloModel.ModeloEntities db = new ModeloModel.ModeloEntities();
try
{
int iCidade = Convert.ToInt32(ddlCidade.SelectedValue);
ModeloModel.Cliente cli = new ModeloModel.Cliente();
cli.IdCliente = 1;
cli.Nome = "Jose";
cli.Cidade = (from c in db.Cidade
where c.IdCidade == iCidade
select c).First();
db.AddToCliente(cli);
db.SaveChanges();
}
catch (Exception erro)
{
Label1.Text = erro.Message;
}
Aguardo uma resposta,
Julio
Nefrodata Sistemas
GOSTEI 0
Nefrodata Ltda
19/01/2009
Carlos a inclusão de registros eu faço dessa maneira mesmo, vou te passar um exemplo, porém minha dúvida é como aplicar uma regra de negócio para Cidade na minha camada de regra de negócios, sua sugestão inicial é perfeita porem não consigo implementa-la. Não gostaria de ter uma parte de minha regra de negócio numa camada e a outra parte no cliente.
ModeloModel.ModeloEntities db = new ModeloModel.ModeloEntities();
try
{
int iCidade = Convert.ToInt32(ddlCidade.SelectedValue);
ModeloModel.Cliente cli = new ModeloModel.Cliente();
cli.IdCliente = 1;
cli.Nome = "Jose";
cli.Cidade = (from c in db.Cidade
where c.IdCidade == iCidade
select c).First();
db.AddToCliente(cli);
db.SaveChanges();
}
catch (Exception erro)
{
Label1.Text = erro.Message;
}
Aguardo uma resposta,
Julio
Nefrodata Sistemas
GOSTEI 0
[devmedia .net]
19/01/2009
Não entendi porque não consegue aplicar...
pode explicar melhor...??
Pois é essa a solução e você não precisa colocar regras de negócio em camada nenhuma se você colocar as validações do .net..
RequiredFieldValidator, com ele você consegue validar se o dropdown está seleciona com valor ou não,
portanto fazendo essa validação na interface não tem porquê fazer em alguma camada para verificar se está preenchido o valor ou não...
E para fazer a validação do dropdown na interface, você coloca o value da opção "Selecione uma cidade" como vazio, mas deve colocar isso nas propriedades do html , onde o drop down é declarado.
Abraços
Carlos Jr
GOSTEI 0
Nefrodata Ltda
19/01/2009
Carlos entendi o que você quis dizer e consegui implementar o que precisava porém fazendo como você disse no momento que disparo o SaveChanges() esta sendo passado um erro.
Se eu faço a inserção dessa maneira (como vc disse):
ModeloModel.ModeloEntities db = new ModeloModel.ModeloEntities();
ModeloModel.Cidade cid = new ModeloModel.Cidade();
cid.IdCidade = 1;
cid.Descricao = "Rio de Janeiro";
ModeloModel.Cliente cli = new ModeloModel.Cliente();
cli.IdCliente = 1;
cli.Cidade = cid;
cli.Nome = "Jose";
db.AddToCliente(cli);
db.SaveChanges();
No momento do SaveChances() ocorre o erro: An error occurred while updating the entries. See the InnerException for details.
Veirifique que a classe quando instanciada dessa maneira não inicializa o EntityKey, mas não sei se o problema é esse.
Se eu faço a inserção dessa maneira:
ModeloModel.ModeloEntities db = new ModeloModel.ModeloEntities();
ModeloModel.Cliente cli = new ModeloModel.Cliente();
cli.IdCliente = 1;
cli.Cidade = (from c in db.Cidade
where c.IdCidade == 1
select c).First();
cli.Nome = "Jose";
db.AddToCliente(cli);
db.SaveChanges();
Não ocorre nenhum erro e a inserção é feita.
O que pode ser esse erro?
Julio
Lifesys Informática
GOSTEI 0
[devmedia .net]
19/01/2009
E aí ,
é isso mesmo que você fez, pois como está utilizando o LINQ você instanciar a classe que deseja incluir na propriedade, pois ele retorno o mesmo tipo.
Quando faz a inserção direta como eu passei ele, não entende que é uma inclusão apenas de cliente e tenta incluir cidade, por isso ocorre o erro.
A sua inclusão está correta, o que terá que fazer é pegar o código que está no dropdown e instanciar a classe cidade pertencente àquele código.
Utilizar o LINQ lhe dá mais rapidez no desenvolvimento, mas em algumas situações você ficará meio engessado.
Existem N maneiras de se fazer a inclusão do cliente, a que você escolheu é uma delas e está correta.
Me envie seu diagrama de classes e uma imagem de como está o diagrama de entidade, apenas mostrandos as tabelas Cliente e Cidade, para ver se podemos melhorar algo ou se assim está legal.
no aguardo..
Abraços
Carlos Jr
GOSTEI 0
Nefrodata Ltda
19/01/2009
Carlos já mandei para vc como esta o meu EDM na mensagem de ID: 2008 só para exemplificação, tenho esse mesmo modelo em outra aplicação maior que estamos desenvolvendo porém com mais campos. Mas com o que você me passou vai dar para validar veja o que eu fiz e verifique se esta correto.
Utilizando o mesmo modelo da mensagem ID: 2008.
RegraNegocio.cs
namespace ModeloModel
{
public partial class Cidade
{
partial void OnIdCidadeChanging(int value)
{
if (value == 0)
throw new ApplicationException("Seleciona uma cidade!");
}
partial void OnDescricaoChanging(string value)
{
if (value == "")
throw new ApplicationException("Descrição da cidade é obrigatório!"); }
}
public partial class Cliente
{
partial void OnNomeChanging(string value)
{
if (value == "")
throw new ApplicationException("Nome do cliente é obrigatório!");
}
}
}
Default.aspx
ModeloModel.ModeloEntities db = new ModeloModel.ModeloEntities();
try
{
ModeloModel.Cidade cid = new ModeloModel.Cidade();
cid.IdCidade = Convert.ToInt32(ddlCidade.SelectedValue);
ModeloModel.Cliente cli = new ModeloModel.Cliente();
cli.IdCliente = Convert.ToInt32(TextBox1.Text);
cli.Nome = TextBox2.Text;
cli.Cidade = (from c in db.Cidade
where c.IdCidade == cid.IdCidade
select c).First();
db.AddToCliente(cli);
db.SaveChanges();
}
catch (Exception erro)
{
Label1.Text = erro.Message;
}
Quando eu associar a cidade selecionada no DropDownList ele vai validar se foi selecionado ou não, além de preenche-la com os registros da tabela de cidades inseri um registro com value = 0 e text = (Selecione uma cidade), então ele vai passar pela camada de validação e retornara o erro para minha interface.
Acho que assim ficou bom, o que você acha, tem uma forma mais correta ou prática de fazer isso??
Aguardo sua resposta!
Julio
Nefrodata Sistemas
GOSTEI 0
[devmedia .net]
19/01/2009
Opa,
Julio, sua solução está correta e funciona perfeitamente..
Como eu lhe disse a única coisa que eu não faria e confundir validação de interface com regras de negócio,
pois na minha opinião , você deixar de selecionar um item na tela é validação de interface que no caso é feita pelo controle RequiredFieldValidator, é a única coisa que poderia ser mudada, o resto está ótimo cara.
Podemos fechar o Chamado ?
Grande Abraço
Carlos Jr
GOSTEI 0
Nefrodata Ltda
19/01/2009
Podemos fechar sim Carlos, obrigado pela ajuda!
GOSTEI 0