8
To report on my application I have created several classes, and each class is responsible for a report, however, there is a repetition of a lot of code by those classes that I would like to avoid, rewriting the code in a way that makes the most of the language’s object orientation features C#.
I will present two classes to illustrate the situation, and all the others will have the structure similar to few attributes that would sweep.
Class RelAlunoAtivoOuInativo
:
using fyiReporting.RDL;
using fyiReporting.RdlViewer;
using System.Data;
using System.Data.SQLite;
using DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BLL
{
public class RelAlunoAtivoOuInativo
{
private RdlViewer reportViewer;
private ViewerToolstrip reportStrip;
private String nomeArquivo;
private StringBuilder query;
private List<string> erros;
private DALConexao conexao;
private Boolean ativoOuInativo;
public RelAlunoAtivoOuInativo(DALConexao conexao, bool ativoOuInativo)
{
this.conexao = conexao;
this.erros = new List<string>();
this.reportViewer = new RdlViewer();
this.reportStrip = new ViewerToolstrip(this.reportViewer);
this.reportStrip.Viewer = this.reportViewer;
this.query = new StringBuilder();
this.query.Append("SELECT id_aluno, nome, telefone, informatica, participa_encontro FROM Alunos WHERE ativo = ?");
this.nomeArquivo = "relatorioGeralAlunoAtivoInativo.rdl";
this.ativoOuInativo = ativoOuInativo;
emitir();
}
public void emitir()
{
PathRelatorio caminhoArquivo = new PathRelatorio(this.nomeArquivo);
if (caminhoArquivo.existeArquivo())
{
try
{
this.reportViewer.SourceFile = new Uri(caminhoArquivo.Path);
this.reportViewer.Parameters += string.Format("conexao={0}", this.conexao.Conexao.ConnectionString);
this.reportViewer.Report.DataSets["Data"].SetData(obterTabela());
this.reportViewer.Rebuild();
this.reportViewer.HideRunButton();
this.reportViewer.Dock = System.Windows.Forms.DockStyle.Fill;
}
catch (Exception ex)
{
this.erros.Add(string.Format("Erro: {0}", ex.Message));
}
}
}
public RdlViewer ReportViewer
{
get
{
return this.reportViewer;
}
}
public ViewerToolstrip ReportStrip
{
get
{
return this.reportStrip;
}
}
public List<string> Erros
{
get
{
return this.erros;
}
}
private DataTable obterTabela()
{
DataTable tabela = new DataTable();
try
{
using (SQLiteConnection conexao = this.conexao.Conexao)
{
using (SQLiteCommand command = conexao.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = this.query.ToString();
command.Parameters.Add("ativo", DbType.Int32).Value = this.ativoOuInativo ? 1 : 0;
conexao.Open();
using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(command))
{
dataAdapter.Fill(tabela);
conexao.Close();
}
}
}
}
catch (Exception ex)
{
this.erros.Add("Erro:" + ex.Message);
return null;
}
return tabela;
}
}
}
Class RelGeralAluno
:
using fyiReporting.RDL;
using fyiReporting.RdlViewer;
using System.Data;
using System.Data.SQLite;
using DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BLL
{
public class RelGeralAluno
{
private RdlViewer reportViewer;
private ViewerToolstrip reportStrip;
private String nomeArquivo;
private StringBuilder query;
private List<string> erros;
private DALConexao conexao;
public RelGeralAluno(DALConexao conexao)
{
this.conexao = conexao;
this.erros = new List<string>();
this.reportViewer = new RdlViewer();
this.reportStrip = new ViewerToolstrip(this.reportViewer);
this.reportStrip.Viewer = this.reportViewer;
this.query = new StringBuilder();
this.query.Append("SELECT nome, data_cadastro, telefone, celular, endereco, email, idade FROM Alunos ");
this.nomeArquivo = "relatorioGeralAlunos.rdl";
emitir();
}
public void emitir()
{
PathRelatorio caminhoArquivo = new PathRelatorio(this.nomeArquivo);
if (caminhoArquivo.existeArquivo())
{
try
{
this.reportViewer.SourceFile = new Uri(caminhoArquivo.Path);
this.reportViewer.Parameters += string.Format("conexao={0}", this.conexao.Conexao.ConnectionString);
this.reportViewer.Report.DataSets["Data"].SetData(obterTabela());
this.reportViewer.Rebuild();
this.reportViewer.HideRunButton();
this.reportViewer.Dock = System.Windows.Forms.DockStyle.Fill;
}
catch (Exception ex)
{
this.erros.Add(string.Format("Erro: {0}", ex.Message));
}
}
}
public RdlViewer ReportViewer
{
get
{
return this.reportViewer;
}
}
public ViewerToolstrip ReportStrip
{
get
{
return this.reportStrip;
}
}
public List<string> Erros
{
get
{
return this.erros;
}
}
private DataTable obterTabela()
{
DataTable tabela = new DataTable();
try
{
using (SQLiteConnection conexao = this.conexao.Conexao)
{
using (SQLiteCommand command = conexao.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = this.query.ToString();
conexao.Open();
using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(command))
{
dataAdapter.Fill(tabela);
conexao.Close();
}
}
}
}
catch (Exception ex)
{
this.erros.Add("Erro:" + ex.Message);
return null;
}
return tabela;
}
}
}
Class implementation:
private void FormRunRelatorio_Load(object sender, EventArgs e)
{
var erros = new List<string>();
switch (this.relatorioSelecionado)
{
case "GeralAluno":
RelGeralAluno relGeralAluno = new RelGeralAluno(new DALConexao(new DadosConexao().String_Conexao));
this.Controls.Add(relGeralAluno.ReportStrip);
this.Controls.Add(relGeralAluno.ReportViewer);
erros = relGeralAluno.Erros;
break;
case "GeralAlunoInativoOuAtivo":
RelAlunoAtivoOuInativo relAlunoAtivoInativo = new RelAlunoAtivoOuInativo(new DALConexao(new DadosConexao().String_Conexao), false);
this.Controls.Add(relAlunoAtivoInativo.ReportStrip);
this.Controls.Add(relAlunoAtivoInativo.ReportViewer);
erros = relAlunoAtivoInativo.Erros;
break;
case mais condicao...
mais codigo...
}
if (erros.Count > 0)
{
foreach (var erro in erros)
MessageBox.Show(erro, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
this.Close();
}
}
Repetition between methods and attributes
The following attributes and methods repeat much between classes, they are:
Attributes
- Attribute reportViewer:
private RdlViewer reportViewer;
- Attribute reportStrip:
private ViewerToolstrip reportStrip;
- Filename attribute:
private String nomeArquivo;
- Query attribute:
private StringBuilder query;
- Error attribute:
private List<string> erros;
- Related attribute:
private DALConexao conexao;
Methods
- Method issuing():
public void emitir()
- Method to obtain Bee():
private DataTable obterTabela()
The way it defined the classes does not seem to me the best way, I know there is a way, but my knowledge is still limited.
Question
How can I avoid all this code repetition, if it is possible to use inheritance or interface or some other feature of object orientation, within good programming practices? Or even if there is some standard or tool within software engineering to avoid the above situation?
Obs: I use Microsoft Visual C# 2012 and the C# version is 5.0 along with the Sqlite database, and the reporting tool is the My-Fyireporting.
Normally I don’t like code review questions very much unless they are very specific (which may stop being code review) or trivial, but I will try to do something, it may not be that complicated. Confirm to me if the only different things in the two classes are the name of the RDL file to be used, the query SQL and an existing parameter in one of them. Out of curiosity, this reporter’s original project was abandoned?
– Maniero
The file name represents the report, and the query also changes, each report has its query, some querys have parameters, the type may vary. but most have no parameter at all.
– gato
The question is whether those are the only differences.
– Maniero
The original project was abandoned, plus this and a Fork of the original and a new version, managed by Peter Gill.
– gato
The class has few differences even, most characteristics repeat in the other class, the codes arrive to be exactly equal.
– gato
I edited the answer by putting examples. I was avoiding because it’s more complicated than it looks. You probably have mistakes in mine, but at least you do what you need (in the general idea). To see how complicated it is to analyze, the answer that has more votes does not do what you need and still received several votes.
– Maniero