How and where to implement business rules in the Entity Framework?

4

I have the following example of a software that uses the Entity Framework , which accesses a database with only one table named Produtos with the following fields:

  • Field int produtoid .
  • Field string nomeproduto .
  • Field int categoriaid .

It also has a form where I do CRUD , see:

HereisthecodeofthetwoEF-generatedfilesthatismyContextandmyclassProdutos.

ClassProdutos:

namespaceCRUD_EF{usingSystem;usingSystem.Collections.Generic;publicpartialclassProdutos{publicintprodutoid{get;set;}publicstringnomeproduto{get;set;}publicintcategoriaid{get;set;}}}

ClassExemploEFEntities:

namespaceCRUD_EF{usingSystem;usingSystem.Data.Entity;usingSystem.Data.Entity.Infrastructure;publicpartialclassExemploEFEntities:DbContext{publicExemploEFEntities():base("name=ExemploEFEntities")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public virtual DbSet<Produtos> Produtos { get; set; }
    }
}

And this is the whole code of my form (Form1.cs):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CRUD_EF
{
    public partial class frmPrincipal : Form
    {
        public frmPrincipal()
        {
            InitializeComponent();
        }

        private void frmPrincipal_Load(object sender, EventArgs e)
        {
            lerProdutos();
        }

        private void lerProdutos() 
        {
            ExemploEFEntities context = new ExemploEFEntities();

            IEnumerable<Produtos> produtos = from p 
                                             in context.Produtos 
                                             select p;

            dataGridViewProdutos.DataSource = produtos.ToList();
        }

        private void incluir(string nomeProduto, int idCategoria) 
        {
            ExemploEFEntities context = new ExemploEFEntities();

            Produtos novoProduto = new Produtos()
            {
                nomeproduto = nomeProduto,
                categoriaid = idCategoria
            };

            context.Produtos.Add(novoProduto);
            context.SaveChanges();

            lerProdutos();
        }

        private void btnIncluir_Click(object sender, EventArgs e)
        {
            incluir(txtNome.Text, Convert.ToInt32(txtCategoriaID.Text));
        }

        private void btnAlterar_Click(object sender, EventArgs e)
        {
            alterar();
        }

        private void alterar() 
        {
            ExemploEFEntities context = new ExemploEFEntities();

            int id = Convert.ToInt32(txtProdutoId.Text);

            Produtos produto = context.Produtos.First(p => p.produtoid == id);
            produto.nomeproduto = txtNome.Text;
            produto.categoriaid = Convert.ToInt32(txtCategoriaID.Text);                        

            context.SaveChanges();

            lerProdutos();
        }

        private void deletar() 
        {
            ExemploEFEntities context = new ExemploEFEntities();

            int id = Convert.ToInt32(txtProdutoId.Text);

            Produtos produto = context.Produtos.First(p => p.produtoid == id);

            context.Produtos.Remove(produto);
            context.SaveChanges();

            lerProdutos();
        }

        private void btnExcluir_Click(object sender, EventArgs e)
        {
            deletar();
        }

        private void query(int id) 
        {
            ExemploEFEntities context = new ExemploEFEntities();

            Produtos produto = context.Produtos.First(p => p.produtoid == id);

            txtProdutoId.Text = produto.produtoid.ToString();
            txtNome.Text = produto.nomeproduto.ToString();
            txtCategoriaID.Text = produto.categoriaid.ToString();
        }

        private void dataGridViewProdutos_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            try 
            {
                int id = Convert.ToInt32(dataGridViewProdutos.Rows[e.RowIndex].Cells[0].Value);

                query(id);
            }
            catch 
            {
                MessageBox.Show("Houve um erro!");
            }
        }
    }
}

My doubt.

Given the entire structure generated by the Entity Framework I would like to know how and where I could implement the business rules?

To facilitate and illustrate the situation we will consider the following rule:

  

It is not allowed to register products with exactly the same name.

How and where would I implement this rule?

    
asked by anonymous 20.05.2016 / 01:22

3 answers

6

Your question is somewhat complex in terms of implementation. Business rules is not an easy subject to be discussed. There is this question where it is explained a bit about this.

But trying to answer a little, you can do it in some ways. I advise two ways. One is by using DataAnnotations , such as the @ TobyMosque comments and the other way will be using IValidableObject .

I do not recommend creating a method just for this, since the framework and the language you are using offer better alternatives.

Using DataAnnotations , you would need to create a new attribute. This answer has an example of how to implement.

If you want to use IValidableObject , you can see an example in this question .

    
20.05.2016 / 04:28
4

For example, before inserting or changing your registry, you could call a (Boolean) method with the necessary rules.

The rules could be defined in the database itself by triggers or even stored procedures that would be called by the application (there are several pros in this type of implementation) / p>

Focusing only on the proposed problem, see an example below:

private void incluir(string nomeProduto, int idCategoria) 
{
    if (RegistroValido(nomeProduto, idCategoria))
    {
        using (ExemploEFEntities context = new ExemploEFEntities())
        {
            Produtos novoProduto = new Produtos()
            {
                nomeproduto = nomeProduto,
                categoriaid = idCategoria
            };

            context.Produtos.Add(novoProduto);
            context.SaveChanges();
        }

        lerProdutos();
    }
}


private bool RegistroValido(string nomeProduto, int idCategoria)
{
    bool retValido = false;
    int erro = 0;
    using (ExemploEFEntities context = new ExemploEFEntities())
    {
        //busca na tabela de produtos um com o mesmo nome
        if (context.Produtos.Count(x => x.nomeproduto.ToUpper().Equals(nomeProduto.ToUpper())) > 0)
            erro = 1;

        if (idCategoria == 0)
            erro = 2;
    }

    swicth (erro)
    {
        case 1:
            MessageBox.Show("Não é permitido cadastrar produtos com o nome exatamente igual.","Atenção!");
            break;
        case 2:
            MessageBox.Show("Não é permitido cadastrar um produto sem categoria.","Atenção!");
            break;
        default:
            retValido = true;
            break;
    }

    return retValido;
}

This is one of the possible scenarios.

    
20.05.2016 / 02:50
0

You would then have several layers, for example:

  • ProductsDAO
  • ProductsRN
  • ProductsForm (I do not like using controller here, I like it).

ProductsDAO would have all CRUD methods in the database.

Products you instantiate ProductsDAO and in the save method you can check if there is no Product with the same name, if positive it throws an Exception (which would be treated in the form).

ProductsForm you instantiate ProductsRN to call the business rule methods and deal with the visual part.

    
20.05.2016 / 03:22