Nesse artigo vou mostrar como criar a camada de persistência de dados com reflection.
O uso de reflection pode diminuir a performance do sistema, para atribuir um valor em uma propriedade da classe, primeiro o algoritmo vai procurar a propriedade da classe e depois vai atribuir o valor, sendo que o uso normal não tem esse tempo de procura.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Reflection
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Cliente oCliente =new Cliente();
oCliente.Name ="Cliente 1";
oCliente.SetValue("Name","Cliente 1");
Console.Read();
}
}
public class Cliente
{
private string _name;
public string Name
{
get { return _name; }
set {_name = value;}
}
public void SetValue(stringnameProperty, object value)
{
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
for (int index = 0; index
Deve ser analisado o que é será importante no desenvolvimento, a perfomance do sistema ou o ganho de tempo no desenvolvimento,utilizo quando preciso criar pequenos projetos ou quando o prazo de entrega é curto.
Separei as classes em pacotes.
EN – Classes de Entidade
DAO – Classes de acesso de dados.
Data – Classes que contém os métodos para inserir, consultar, atualizar e excluir dados no banco de dados.
As classes desses pacotes são acessíveis somente na dll que foram criadas. Para acessar os métodos criei uma classe facade chamada FacadeDAO, essa classe é utilizada para expor os métodos das classes DAO, para acessar as propriedades das classes EN, foram criadas interfaces.
Abaixo mostro em diagramas como ficou a estrutura.
No pacote Data foi criado uma classe abstrata e duas classes que herdam dela, a classe DatabasePostgresql disponibiliza métodos para acessar o banco de dados PostgreSql e a classe DatabaseSqlServer disponibiliza métodos para acessar o banco de dados Sql Server.
A classe Database foram criados métodos abstratos, obrigando as classes que herdam implementar os métodos. Isso disponibiliza ao sistema acessar 2 bancos diferentes.
Classe Database.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace Persistencia.Data.Base
{
abstract class Database
{
private int _commandTimeOut;
public int CommandTimeOut
{
get { return _commandTimeOut; }
set {_commandTimeOut = value;}
}
publicDatabase(int commandTimeOut)
{
this.CommandTimeOut =commandTimeOut;
}
public abstract ConnectionStateStateConnection { get; }
public abstract voidConnectionOpen(string stringConnection);
public abstract voidConnectionClose();
public abstract voidBeginTransacTion();
public abstract voidComitTransacTion();
public abstract voidRollBack();
public abstract DataSetExecuteDataAdapter_DataSet(string strSql);
public abstract DataTableExecuteDataAdapter_DataTable(string strSql);
public abstract DataRowExecuteDataRow(string strSql);
public abstract voidExecuteDataReader(string strSql, Actionaction);
public abstract objectExecuteScalar(string strSql);
public abstract objectExecuteScalar(string strSql, ListparameterCollection);
public abstract voidExecuteNonQuery(string strSql, ListparameterCollection);
public abstract voidExecuteNonQuery(string strSql);
public abstract IDbDataParameterCreateObjectParameter(bool isNullable);
public abstract stringCommandLastIdentity();
}
}
Classe DatabasePostgreSql. Para usar essa classe é preciso adicionar a dll Npgsql.dll na referência no projeto.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Npgsql;
using Persistencia.Data.Base;
namespace Persistencia.Data
{
class DatabasePostgreSQL : Database
{
public override ConnectionStateStateConnection
{
get
{
if(oNpgsqlConnection != null)
{ returnoNpgsqlConnection.State; }
else
{ returnConnectionState.Closed;}
}
}
private NpgsqlConnection oNpgsqlConnection;
private NpgsqlTransaction oNpgsqlTransaction;
publicDatabasePostgreSQL(int commandTimeOut)
: base(commandTimeOut)
{
}
public override voidConnectionOpen(string stringConnection)
{
oNpgsqlConnection = new NpgsqlConnection(stringConnection);
oNpgsqlConnection.Open();
}
public override voidConnectionClose()
{
if(oNpgsqlTransaction != null)
{
oNpgsqlTransaction.Dispose();
oNpgsqlTransaction = null;
}
if(oNpgsqlConnection != null)
{
if(oNpgsqlConnection.State == ConnectionState.Open)
{
oNpgsqlConnection.Close();
}
oNpgsqlConnection.Dispose();
oNpgsqlConnection = null;
}
}
public override voidBeginTransacTion()
{
oNpgsqlTransaction = oNpgsqlConnection.BeginTransaction();
}
public override voidComitTransacTion()
{
oNpgsqlTransaction.Commit();
}
public override voidRollBack()
{
oNpgsqlTransaction.Rollback();
}
public override DataSetExecuteDataAdapter_DataSet(string strSql)
{
DataSetoDataSet = newDataSet();
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
NpgsqlDataAdapteroNpgsqlDataAdapter = new NpgsqlDataAdapter(oNpgsqlCommand);
oNpgsqlDataAdapter.Fill(oDataSet);
returnoDataSet;
}
public override DataTableExecuteDataAdapter_DataTable(string strSql)
{
DataTableoDataTable = newDataTable();
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
NpgsqlDataAdapteroNpgsqlDataAdapter = new NpgsqlDataAdapter(oNpgsqlCommand);
oNpgsqlDataAdapter.Fill(oDataTable);
returnoDataTable;
}
public override DataRowExecuteDataRow(string strSql)
{
DataRowoDataRow = null;
DataTableoDataTable = newDataTable();
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
NpgsqlDataAdapteroNpgsqlDataAdapter = new NpgsqlDataAdapter(oNpgsqlCommand);
oNpgsqlDataAdapter.Fill(oDataTable);
if(oDataTable.Rows.Count> 0)
{
oDataRow =oDataTable.Rows[0];
}
returnoDataRow;
}
public override voidExecuteDataReader(string strSql, Actionaction)
{
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
NpgsqlDataReaderoNpgsqlDataReader = oNpgsqlCommand.ExecuteReader();
while(oNpgsqlDataReader.Read())
{
action(oNpgsqlDataReader);
}
}
public override objectExecuteScalar(string strSql)
{
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
returnoNpgsqlCommand.ExecuteScalar();
}
public override objectExecuteScalar(string strSql, ListparameterCollection)
{
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
parameterCollection.ForEach(delegate(IDbDataParameter item){
oNpgsqlCommand.Parameters.Add(item);
});
returnoNpgsqlCommand.ExecuteScalar();
}
public override voidExecuteNonQuery(string strSql, ListparameterCollection)
{
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
parameterCollection.ForEach(delegate(IDbDataParameter item){
oNpgsqlCommand.Parameters.Add(item);
});
oNpgsqlCommand.ExecuteNonQuery();
}
public override voidExecuteNonQuery(string strSql)
{
NpgsqlCommandoNpgsqlCommand = newNpgsqlCommand();
oNpgsqlCommand.CommandText= strSql;
oNpgsqlCommand.CommandTimeout= CommandTimeOut;
oNpgsqlCommand.Connection= oNpgsqlConnection;
oNpgsqlCommand.Transaction= oNpgsqlTransaction;
oNpgsqlCommand.ExecuteNonQuery();
}
public override IDbDataParameterCreateObjectParameter(bool isNullable)
{
NpgsqlParameteroNpgsqlParameter = newNpgsqlParameter();
oNpgsqlParameter.IsNullable= isNullable;
return oNpgsqlParameter;
}
public override stringCommandLastIdentity()
{
return "SELECT lastval() AS Id;";
}
}
}
Classe DatabaseSqlServer.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Persistencia.Data.Base;
namespace Persistencia.Data
{
sealed class DatabaseSqlServer: Database
{
public override ConnectionStateStateConnection
{
get
{
if(oSqlConnection != null)
{ returnoSqlConnection.State; }
else
{ returnConnectionState.Closed;}
}
}
private SqlConnection oSqlConnection;
private SqlTransaction oSqlTransaction;
publicDatabaseSqlServer(int commandTimeOut)
: base(commandTimeOut)
{
}
public override voidConnectionOpen(string stringConnection)
{
oSqlConnection =new SqlConnection(stringConnection);
oSqlConnection.Open();
}
public override voidConnectionClose()
{
if(oSqlTransaction != null)
{
oSqlTransaction.Dispose();
oSqlTransaction = null;
}
if(oSqlConnection != null)
{
if(oSqlConnection.State == ConnectionState.Open)
{
oSqlConnection.Close();
}
oSqlConnection.Dispose();
oSqlConnection = null;
}
}
public override voidBeginTransacTion()
{
oSqlTransaction =oSqlConnection.BeginTransaction();
}
public override voidComitTransacTion()
{
oSqlTransaction.Commit();
}
public override voidRollBack()
{
oSqlTransaction.Rollback();
}
public override DataSetExecuteDataAdapter_DataSet(string strSql)
{
DataSetoDataSet = newDataSet();
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
SqlDataAdapteroSqlDataAdapter = newSqlDataAdapter(oSqlCommand);
oSqlDataAdapter.Fill(oDataSet);
returnoDataSet;
}
public override DataTableExecuteDataAdapter_DataTable(string strSql)
{
DataTableoDataTable = newDataTable();
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
SqlDataAdapteroSqlDataAdapter = newSqlDataAdapter(oSqlCommand);
oSqlDataAdapter.Fill(oDataTable);
returnoDataTable;
}
public override DataRowExecuteDataRow(string strSql)
{
DataRowoDataRow = null;
DataTableoDataTable = newDataTable();
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
SqlDataAdapteroSqlDataAdapter = newSqlDataAdapter(oSqlCommand);
oSqlDataAdapter.Fill(oDataTable);
if(oDataTable.Rows.Count> 0)
{
oDataRow =oDataTable.Rows[0];
}
returnoDataRow;
}
public override voidExecuteDataReader(string strSql, Actionaction)
{
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
SqlDataReaderoSqlDataReader = oSqlCommand.ExecuteReader();
while(oSqlDataReader.Read())
{
action(oSqlDataReader);
}
}
public override objectExecuteScalar(string strSql)
{
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
returnoSqlCommand.ExecuteScalar();
}
public override object ExecuteScalar(string strSql, List parameterCollection)
{
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
parameterCollection.ForEach(delegate(IDbDataParameter item){
oSqlCommand.Parameters.Add(item);
});
returnoSqlCommand.ExecuteScalar();
}
public override voidExecuteNonQuery(string strSql, ListparameterCollection)
{
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
parameterCollection.ForEach(delegate(IDbDataParameter item){
oSqlCommand.Parameters.Add(item);
});
oSqlCommand.ExecuteNonQuery();
}
public override voidExecuteNonQuery(string strSql)
{
SqlCommandoSqlCommand = newSqlCommand();
oSqlCommand.CommandText= strSql;
oSqlCommand.CommandTimeout= CommandTimeOut;
oSqlCommand.Connection= oSqlConnection;
oSqlCommand.Transaction= oSqlTransaction;
oSqlCommand.ExecuteNonQuery();
}
public override IDbDataParameterCreateObjectParameter(bool isNullable)
{
SqlParameteroSqlParameter = newSqlParameter();
oSqlParameter.IsNullable= isNullable;
return oSqlParameter;
}
public override stringCommandLastIdentity()
{
return "SELECT SCOPE_IDENTITY() AS Id;";
}
}
}
No pacote EN foram criadas as classes e enumeradores:
StatusObject
FieldAttribute = classe para configurar as propriedades das classes entidades.
TypeProperty = enumerador para indicar se a propriedade é um tipo,referência ou uma coleção.
BaseEN = classe que atribuí e retorna valores nas propriedades, cria os comandos INSERT, DELETE, UPDATE E SELECT para serem usados nas classesDAO.
public enum TypeProperty
{
Type = 0,//Indica que a propriedade é um tipo.
Collection = 1,//Indica que a propriedade é uma coleção.
Reference = 2,//Indica que a propriedade é uma referência.
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Persistencia.EN
{
public enum TypeProperty
{
Type = 0,//Indica que a propriedade é um tipo.
Collection = 1,//Indica que a propriedade é uma coleção.
Reference = 2,//Indica que a propriedade é uma referência.
}
public enum StatusObject
{
New = 0,//Indica que a classe foi criada.
Loaded = 1,//Indica que os dados foram carregados do banco de dados.
Changed = 2,//Indica que a classe foi alterada.
DeletedLoaded = 3,//Indica que o objeto pode ser excluído do banco de dados,informa que esse objeto foi carregado.
DeletedChanged = 3,//Indica que o objeto pode ser excluído do banco de dados,informa que esse objeto foi alterado.
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace Persistencia.EN.Base
{
public sealed class FieldAttribute : Attribute
{
private bool_isPrimaryKey;//Indica que o campo no banco de dados éuma chave primária.
private bool_isForeignKey;//Indica que o campo no banco de dados éuma chave estrangeira.
private TypeProperty _typeProperty;//Indica que tipo é a propriedade na classe.
private string_nameField;//Nome do campo no banco de dados.
private string_nameParam;//Nome do parâmetro utilizado nos métodosna classe DAO.
private int_length;//Tamanho do campo no banco de dados.
private DbType_dbType;//Tipo do campo no banco de dados.
private bool_isNull;//Indica se o campo pode ser nulo no banco dedados.
private byte_precision;//Precição do campo.
private byte_scale;//Escala do campo.
private object_value;//Propriedade utilizado para passar o valor dapropriedade.
public bool IsPrimaryKey
{
get { return _isPrimaryKey; }
private set { _isPrimaryKey =value; }
}
public bool IsForeignKey
{
get { return _isForeignKey; }
private set { _isForeignKey =value; }
}
publicTypeProperty TypeProperty
{
get { return _typeProperty; }
private set { _typeProperty =value; }
}
public string NameField
{
get { return _nameField; }
private set { _nameField =value; }
}
public string NameParam
{
get { return _nameParam; }
private set { _nameParam =value; }
}
public int Length
{
get { return _length; }
private set { _length = value; }
}
public DbType DbType
{
get { return _dbType; }
private set { _dbType = value; }
}
public bool IsNull
{
get { return _isNull; }
private set { _isNull = value; }
}
public byte Precision
{
get { return _precision; }
private set { _precision =value; }
}
public byte Scale
{
get { return _scale; }
private set { _scale = value; }
}
public objectValue
{
get { return _value; }
set {_value = value;}
}
publicFieldAttribute(bool isPrimaryKey, bool isForeignKey, TypeProperty typeProperty, string nameField, stringnameParam, int length, DbTypedbType, bool isNull)
{
this.IsPrimaryKey =isPrimaryKey;
this.IsForeignKey =isForeignKey;
this.TypeProperty =typeProperty;
this.NameField =nameField;
this.NameParam =nameParam;
this.Length =length;
this.DbType =dbType;
this.IsNull =isNull;
}
publicFieldAttribute(bool isPrimaryKey, bool isForeignKey, TypeProperty typeProperty, string nameField, stringnameParam, int length, DbTypedbType, bool isNull, byteprecision, byte scale)
{
this.IsPrimaryKey =isPrimaryKey;
this.IsForeignKey =isForeignKey;
this.TypeProperty =typeProperty;
this.NameField =nameField;
this.NameParam =nameParam;
this.Length =length;
this.DbType =dbType;
this.IsNull =isNull;
this.Precision =precision;
this.Scale =scale;
}
}
}
Aclasse BaseEN é onde realmente utilizamos reflection.Vamos usar aclasses:
PropertyInfo
Precisamos de ssa classe para coletar as informações do campo no banco de dados, comotamanho, tipo, etc.
Assembly
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
namespace Persistencia.EN.Base
{
public abstract class BaseEN
{
private StatusObjectstatus;//Variável para guardar o status do objeto.
private stringnameSchema;//Nome do schema que a tabela pertence nobanco de dados.
private stringnameTable;//Nome da tabela no banco de dados.
private stringnameIdParent;//Utilizado quando a classe tem umaclasse pai, no construtor a classe entidade passa para a classe base o nome
// da propriedade.
private FacadeDAO_oFacadeDAO;//Essa variável vai ser utilizada nasclasses Entidade.
private Int64_id;//Todas as classes entidade vai ter umapropriedade Id.
protected FacadeDAOoFacadeDAO
{
get { return _oFacadeDAO; }
}
[FieldAttribute(true,false, TypeProperty.Type, "bgId","@bgId", 0,System.Data.DbType.Int64, false)]//Configura apropriedade para o banco de dados.
public Int64 Id
{
get { return _id; }
set { _id = value; }
}
///
/// Construtor paraclasse de entidade que não é uma classe filho.
///
/// Nome do schema que a tabela pertence no banco de dados.
/// Nome da tabela no banco de dados.
/// Objeto da classe FacadeDAO.
public BaseEN(string nameSchema, string nameTable, FacadeDAOoFacadeDAO)
{
this.status = StatusObject.New;
this.nameSchema =nameSchema;
this.nameTable =nameTable;
this._oFacadeDAO =oFacadeDAO;
}
///
/// Construtor paraclasse de entidade que é uma classe filho.
///
/// Nome do schema que a tabela pertence no banco de dados.
/// Nome da tabela no banco de dados.
/// Nome da propriedade que é pai da classe.
/// Objeto da classe FacadeDAO.
public BaseEN(string nameSchema, string nameTable, stringnameIdParent, FacadeDAO oFacadeDAO)
{
this.status = StatusObject.New;
this.nameSchema =nameSchema;
this.nameTable =nameTable;
this.nameIdParent =nameIdParent;
this._oFacadeDAO =oFacadeDAO;
}
///
/// Obtém o status da classe.
///
public StatusObject GetStatus()
{
return this.status;
}
///
/// Indica para aclasse DAO que essé objeto vai ser excluído do banco de dados.
///
public void Remove()
{
if (this.status == StatusObject.Loaded)
{
this.status = StatusObject.DeletedLoaded;
}
else if (this.status == StatusObject.Changed)
{
this.status = StatusObject.DeletedChanged;
}
}
///
/// Cancela a exclusão do banco de dados.
///
public void UnRemove()
{
if (this.status == StatusObject.DeletedLoaded)
{
this.status = StatusObject.Loaded;
}
else if (this.status == StatusObject.DeletedChanged)
{
this.status = StatusObject.Changed;
}
}
///
/// Altera o status da classe.
///
internal void SetStatus(StatusObjectstatusObject)
{
this.status = statusObject;
}
///
/// Cria uma novainstância do classe.
///
internal BaseEN NewInstance()
{
AssemblyoAssembly = this.GetType().Assembly;
//Cria uma nova instância, passando comoparâmetro o objeto da classe FacadeDAO.
return (BaseEN)oAssembly.CreateInstance(this.GetType().FullName,false, BindingFlags.CreateInstance, null,new object[] { this._oFacadeDAO}, null, null);
}
///
/// Constrói eretorna o comando SELECT.
///
internal string GetSelect()
{
returngetSelect(null, null,null);
}
///
/// Constrói eretorna o comando SELECT.
///
internal string GetSelect(longid)
{
returngetSelect(id, null, null);
}
///
/// Constrói eretorna o comando SELECT.
///
internal string GetSelectParent(longidParent)
{
returngetSelect(null, idParent, nameIdParent);
}
///
/// Constrói eretorna o comando INSERT.
///
internal string GetInsert()
{
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
StringBuilderoStringBuilder = newStringBuilder();
oStringBuilder.Append(String.Format("INSERT INTO {0}.{1}(", this.nameSchema, this.nameTable));
boolisFirstColumn = true;
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
stringcarac = ",";
if(isFirstColumn)
{
carac = "";
}
if(!oFieldAttribute.IsPrimaryKey&& !oFieldAttribute.IsForeignKey &&oFieldAttribute.TypeProperty != TypeProperty.Collection)
{
oStringBuilder.Append(String.Format("{0}{1}",carac, oFieldAttribute.NameField));
isFirstColumn = false;
}
}
}
oStringBuilder.Append(")VALUES(");
isFirstColumn =true;
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
stringcarac = ",";
if(isFirstColumn)
{
carac = "";
}
if(!oFieldAttribute.IsPrimaryKey&& !oFieldAttribute.IsForeignKey &&oFieldAttribute.TypeProperty != TypeProperty.Collection)
{
oStringBuilder.Append(String.Format("{0}{1}",carac, oFieldAttribute.NameParam));
isFirstColumn = false;
}
}
}
oStringBuilder.Append(")");
returnoStringBuilder.ToString();
}
///
/// Constrói eretorna o comando UPDATE.
///
internal string GetUpdate()
{
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
StringBuilderoStringBuilder = newStringBuilder();
oStringBuilder.Append(String.Format("UPDATE {0}.{1} SET ", this.nameSchema, this.nameTable));
boolisFirstColumn = true;
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
stringcarac = ",";
if(isFirstColumn)
{
carac = "";
}
if(!oFieldAttribute.IsPrimaryKey&& !oFieldAttribute.IsForeignKey &&oFieldAttribute.TypeProperty != TypeProperty.Collection)
{
oStringBuilder.Append(String.Format("{0}{1} ={2}", carac, oFieldAttribute.NameField,oFieldAttribute.NameParam));
isFirstColumn = false;
}
}
}
oStringBuilder.Append(String.Format(" WHERE bgId = {0}", this.Id));
return oStringBuilder.ToString();
}
///
/// Constrói eretorna o comando DELETE.
///
internal string GetDelete()
{
return String.Format("DELETE FROM {0}.{1} WHERE bgId = {2}", this.nameSchema, this.nameTable, this.Id);
}
///
/// Retorna um coleçãode objetos da classe FieldAttribute que vai ser utilizada na classes DAO.
///
internal ListGetFieldAttributeCollection()
{
List fieldAttributeCollection = new List();
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
if(!oFieldAttribute.IsForeignKey&& oFieldAttribute.TypeProperty !=TypeProperty.Collection)
{
if(oFieldAttribute.TypeProperty == TypeProperty.Type)
{
oFieldAttribute.Value =oPropertyInfo.GetValue(this, null);
}
elseif (oFieldAttribute.TypeProperty== TypeProperty.Reference)
{
BaseENoBaseEN = (BaseEN)oPropertyInfo.GetValue(this, null);
if(oBaseEN == null)
{
oFieldAttribute.Value = null;
}
else
{
oFieldAttribute.Value =oBaseEN.Id;
}
}
fieldAttributeCollection.Add(oFieldAttribute);
}
}
}
returnfieldAttributeCollection;
}
///
/// Atribuí osvalores para as propriedades da classe.
///
internal void SetValuesProperties(DataRowoDataRow, int level)
{
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
if(oFieldAttribute.TypeProperty == TypeProperty.Type)
{
objectvalue = oDataRow[String.Format("{0}_{1}_{2}",this.nameSchema,this.nameTable,oFieldAttribute.NameField)];
oPropertyInfo.SetValue(this,value, null);
}
elseif (oFieldAttribute.TypeProperty== TypeProperty.Reference)
{
if(level + 1< 2)
{
AssemblyoAssembly = this.GetType().Assembly;
stringnameAssembly = this.GetType().FullName;
nameAssembly = nameAssembly.Substring(0, nameAssembly.LastIndexOf('.'));
nameAssembly = String.Format("{0}.{1}EN",nameAssembly, oPropertyInfo.PropertyType.Name.Substring(1));
//Cria uma novainstância, passando como parâmetro o objeto da classe FacadeDAO.
BaseEN oBaseEN = (BaseEN)oAssembly.CreateInstance(nameAssembly,false, BindingFlags.CreateInstance, null,new object[] { this._oFacadeDAO}, null, null);
objectvalueId = oDataRow[String.Format("{0}_{1}_bgId",oBaseEN.nameSchema, oBaseEN.nameTable)];
if(valueId != DBNull.Value &&valueId != null)
{
oPropertyInfo.SetValue(this,oBaseEN, null);
oBaseEN.SetValuesProperties(oDataRow, level + 1);
}
}
}
}
}
this.status = StatusObject.Loaded;
}
///
/// Monta o comandoSELECT de acordo com as propriedades.
///
private string getSelect(long? id, long? idParent, stringnameIdParent)
{
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
StringBuilderoStringBuilder = newStringBuilder();
StringBuilderjoinStringBuilder = newStringBuilder();
oStringBuilder.Append("SELECT ");
oStringBuilder.Append(this.getFields());
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
if(oFieldAttribute.TypeProperty == TypeProperty.Reference &&!oFieldAttribute.IsForeignKey)
{
BaseENoBaseEN = (BaseEN)oPropertyInfo.GetValue(this, null);
if(oBaseEN == null)
{
AssemblyoAssembly = this.GetType().Assembly;
stringnameAssembly = this.GetType().FullName;
nameAssembly = nameAssembly.Substring(0, nameAssembly.LastIndexOf('.'));
nameAssembly = String.Format("{0}.{1}EN",nameAssembly, oPropertyInfo.PropertyType.Name.Substring(1));
//Cria uma novainstância, passando como parâmetro o objeto da classe FacadeDAO.
oBaseEN= (BaseEN)oAssembly.CreateInstance(nameAssembly, false, BindingFlags.CreateInstance, null,new object[] { this._oFacadeDAO}, null, null);
}
oStringBuilder.Append(String.Format(",{0}",oBaseEN.getFields()));
if(!oFieldAttribute.IsNull)
{
joinStringBuilder.Append(String.Format(" INNERJOIN {0}.{1} AS {0}_{1} ON {0}_{1}.bgId = {2}_{3}.{4} ", oBaseEN.nameSchema, oBaseEN.nameTable,this.nameSchema,this.nameTable,oFieldAttribute.NameField));
}
else
{
joinStringBuilder.Append(String.Format(" LEFTJOIN {0}.{1} AS {0}_{1} ON {0}_{1}.bgId = {2}_{3}.{4} ", oBaseEN.nameSchema, oBaseEN.nameTable,this.nameSchema,this.nameTable,oFieldAttribute.NameField));
}
}
}
}
oStringBuilder.Append(String.Format(" FROM {0}.{1} AS {0}_{1} ", this.nameSchema, this.nameTable));
oStringBuilder.Append(joinStringBuilder.ToString());
if (id != null)
{
oStringBuilder.Append(String.Format(" WHERE{0}_{1}.bgId = {2} ", this.nameSchema, this.nameTable, id.Value));
}
else if (idParent != null)
{
oStringBuilder.Append(String.Format(" WHERE{0}_{1}.{2} = {3} ", this.nameSchema, this.nameTable, nameIdParent, idParent.Value));
}
return oStringBuilder.ToString();
}
///
/// Método que alterao status da classe.
///
protected void InformPropertyChanged()
{
if (this.status == StatusObject.Loaded)
{
this.status = StatusObject.Changed;
}
}
///
/// Retorna os campospara montar o comando SELECT.
///
private string getFields()
{
PropertyInfo[]arrayPropertyInfo = this.GetType().GetProperties();
StringBuilderoStringBuilder = newStringBuilder();
boolisFirstColumn = true;
for (int index = 0; index 0)
{
FieldAttributeoFieldAttribute = (FieldAttribute)arrayFieldAttribute[0];
stringcarac = ",";
if(isFirstColumn)
{
carac = "";
}
if(!oFieldAttribute.IsForeignKey&& oFieldAttribute.TypeProperty !=TypeProperty.Collection)
{
oStringBuilder.Append(String.Format("{0}{1}_{2}.{3}AS {1}_{2}_{3}", carac, this.nameSchema, this.nameTable, oFieldAttribute.NameField));
isFirstColumn = false;
}
}
}
returnoStringBuilder.ToString();
}
}
}
As classes entidades vamos configurar dessa forma.
Quando uma propriedade é um tipo.
[FieldAttribute(false, false, TypeProperty.Type,"vcName", "@vcName",150, System.Data.DbType.String, false)]
public stringName
{
get { return _name; }
set { _name = value; base.InformPropertyChanged();}
}
Quando uma propriedade é uma referência. É criado uma propriedade com o tipo Int64 e outra com o tipo da classe. Quando os valores são atribuídos a classe, o método só preenche as propriedade da classe e com as classes que estão relacionadas.Ex:
A classe Marido está relacionada com a classe Esposa, a classe Esposa está com a classe está relacionada com a classe Cunhada, no momento do preenchimento as classes que serão preenchidas serão a classe Marido e a classe Esposa, a classe Cunhada só será preenchida quando for acessada (Esposa.Cunhada).
É quando vamos utilizar a propriedade Int64 que contém o id da classe que não foi preenchida.
[FieldAttribute(false, true, TypeProperty.Type,"bgIdCunhada", "@bgIdCunhada", 0,System.Data.DbType.Int64, false)]
public Int64oIdCunhada
{
get { return _oIdCunhada; }
set {_oIdCunhada = value;}
}
[FieldAttribute(false, false, TypeProperty.Reference,"bgIdCunhada", "@bgIdCunhada", 0,System.Data.DbType.Int64, false)]
publicICunhada oCunhada
{
get
{
if ((_oCunhada ==null ||_oCunhada.Id ==0) &&this.oIdCunhada> 0)
{
_oCunhada = (CunhadaEN)new Persistencia.DAO.CunhadaDAO(base.oFacadeDAO).Read(this.oIdCunhada);
}
return _oCunhada;
}
set { _oCunhada =(CunhadaEN)value;base.InformPropertyChanged();}
}
Quando uma propriedade é uma coleção.
[FieldAttribute(false, false, TypeProperty.Collection,"", "@",0, System.Data.DbType.Int64, false)]
public List FilhoCollection
{
get { return _filhoCollection; }
set {_filhoCollection = value;base.InformPropertyChanged();}
}
No construtor da classe vamos passar o nome do schema, nome da tabela e o objeto da classe FacadeDAO.
publicTabelaEN(FacadeDAO oFacadeDAO)
: base("dbo","tbTabela", oFacadeDAO)
{
}
Aqui é estrutura da classe entidade.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Persistencia.EN.Base;
using Persistencia.EN.Interface;
namespace Persistencia.EN
{
internal sealed class EsposaEN : BaseEN,IEsposa
{
private string _name;
private Int64 _oIdCunhada;
private CunhadaEN_oCunhada;
private List _filhoCollection;
public StatusObject StatusObjeto
{
get { return base.GetStatus(); }
}
[FieldAttribute(false, false, TypeProperty.Type,"vcName", "@vcName",150, System.Data.DbType.String, false)]
public string Name
{
get { return _name; }
set {_name = value;base.InformPropertyChanged();}
}
[FieldAttribute(false, true, TypeProperty.Type,"bgIdCunhada", "@bgIdCunhada", 0,System.Data.DbType.Int64, false)]
public Int64 oIdCunhada
{
get { return _oIdCunhada; }
set {_oIdCunhada = value;}
}
[FieldAttribute(false, false, TypeProperty.Reference,"bgIdCunhada", "@bgIdCunhada", 0,System.Data.DbType.Int64, false)]
public ICunhada oCunhada
{
get
{
if ((_oCunhada ==null ||_oCunhada.Id ==0) &&this.oIdCunhada> 0)
{
_oCunhada = (CunhadaEN)new Persistencia.DAO.CunhadaDAO(base.oFacadeDAO).Read(this.oIdCunhada);
}
return _oCunhada;
}
set { _oCunhada =(CunhadaEN)value;base.InformPropertyChanged();}
}
[FieldAttribute(false, false, TypeProperty.Collection,"", "@",0, System.Data.DbType.Int64, false)]
public ListFilhoCollection
{
get { return _filhoCollection; }
set {_filhoCollection = value;base.InformPropertyChanged();}
}
public EsposaEN(FacadeDAOoFacadeDAO)
: base("dbo","tbEsposa", oFacadeDAO)//public = Caso for usar o postgresql
{
}
}
}
Aqui é estrutura da interface.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Persistencia.EN.Base;
namespace Persistencia.EN.Interface
{
public interface IEsposa
{
StatusObjectStatusObjeto { get; }
Int64 Id{ get; }
string Name{ get; set; }
ICunhadaoCunhada { get; set;}
List FilhoCollection { get;set; }
void Remove();
void UnRemove();
}
}
No pacote DAO foi criada uma classe abstrata BaseDAO.
Os métodos públicos da classe:
Write
Read = carrega o objeto com os dados do banco de dados.
ReadAll
ReadAllParent
Os métodos privados da classe:
insert
update
delete
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Persistencia.EN.Base;
using Persistencia.Data.Base;
namespace Persistencia.DAO.Base
{
class BaseDAO
{
///
/// Escreve no bancode dados
///
protected void Write(DatabaseoDatabase, BaseEN oBaseEN)
{
StatusObject status = oBaseEN.GetStatus();
if(status == StatusObject.New)
{
insert(oDatabase, oBaseEN);
}
else if (status ==StatusObject.Changed)
{
update(oDatabase, oBaseEN);
}
else if (status ==StatusObject.DeletedChanged || status ==StatusObject.DeletedLoaded)
{
delete(oDatabase, oBaseEN);
}
}
///
/// Lê o registro nobanco de dados
///
protected void Read(DatabaseoDatabase, BaseEN oBaseEN, long id)
{
DataRowoDataRow = oDatabase.ExecuteDataRow(oBaseEN.GetSelect(id));
if(oDataRow != null)
{
oBaseEN.SetValuesProperties(oDataRow,0);
}
else
{
oBaseEN = null;
}
}
///
/// Lê uma coleção deregistros no banco de dados.
///
protected void ReadAll(DatabaseoDatabase, BaseEN oBaseEN, Actionaction)
{
DataTableoDataTable = oDatabase.ExecuteDataAdapter_DataTable(oBaseEN.GetSelect());
for (int index = 0; index
/// Lê uma coleção deregistro no banco de dados, utilizado quando a classe tem filhos.
///
protected void ReadAllParent(DatabaseoDatabase, BaseEN oBaseEN, long idParent, Action action)
{
DataTableoDataTable = oDatabase.ExecuteDataAdapter_DataTable(oBaseEN.GetSelectParent(idParent));
for (int index = 0; index
/// Insere o registrono banco de dados.
///
private void insert(DatabaseoDatabase, BaseEN oBaseEN)
{
List parameterCollection =new List();
oBaseEN.GetFieldAttributeCollection().ForEach(delegate(FieldAttribute item){
IDbDataParameteroIDbDataParameter = oDatabase.CreateObjectParameter(item.IsNull);
oIDbDataParameter.SourceColumn =item.NameField;
oIDbDataParameter.ParameterName =item.NameParam;
oIDbDataParameter.Size = item.Length;
oIDbDataParameter.Precision =item.Precision;
oIDbDataParameter.Scale = item.Scale;
oIDbDataParameter.DbType = item.DbType;
oIDbDataParameter.Value = item.Value;
parameterCollection.Add(oIDbDataParameter);
});
objectid = oDatabase.ExecuteScalar(String.Format("{0};{1}", oBaseEN.GetInsert(), oDatabase.CommandLastIdentity()),parameterCollection);
oBaseEN.Id= long.Parse(id.ToString());
}
///
/// Atualiza oregistro no banco de dados.
///
private void update(DatabaseoDatabase, BaseEN oBaseEN)
{
List parameterCollection =new List();
oBaseEN.GetFieldAttributeCollection().ForEach(delegate(FieldAttribute item){
IDbDataParameteroIDbDataParameter = oDatabase.CreateObjectParameter(item.IsNull);
oIDbDataParameter.SourceColumn =item.NameField;
oIDbDataParameter.ParameterName =item.NameParam;
oIDbDataParameter.Size = item.Length;
oIDbDataParameter.Precision =item.Precision;
oIDbDataParameter.Scale = item.Scale;
oIDbDataParameter.DbType = item.DbType;
oIDbDataParameter.Value = item.Value;
parameterCollection.Add(oIDbDataParameter);
});
oDatabase.ExecuteNonQuery(oBaseEN.GetUpdate(), parameterCollection);
}
///
/// Exclui o registrono banco de dados.
///
private void delete(DatabaseoDatabase, BaseEN oBaseEN)
{
oDatabase.ExecuteNonQuery(oBaseEN.GetDelete());
}
}
}
Aqui é estrutura de uma classe DAO que não tem filhos.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Persistencia.DAO.Base;
using Persistencia.EN;
using Persistencia.EN.Interface;
using Persistencia.EN.Base;
using Persistencia.Data.Base;
namespace Persistencia.DAO
{
class CunhadaDAO : BaseDAO
{
private FacadeDAO oFacadeDAO;
publicCunhadaDAO(FacadeDAO oFacadeDAO)
{
this.oFacadeDAO =oFacadeDAO;
}
public voidWrite(ICunhada oCunhada)
{
DatabaseoDatabase = oFacadeDAO.CreateInstanceDatabase();
try
{
oDatabase.ConnectionOpen(oFacadeDAO.GetStringConnection());
base.Write(oDatabase, (CunhadaEN)oCunhada);
oDatabase.ConnectionClose();
}
catch (Exception oException)
{
oDatabase.ConnectionClose();
throwoException;
}
}
public ICunhada Read(longid)
{
CunhadaEN oCunhadaEN = new CunhadaEN(oFacadeDAO);
Database oDatabase =oFacadeDAO.CreateInstanceDatabase();
try
{
oDatabase.ConnectionOpen(oFacadeDAO.GetStringConnection());
base.Read(oDatabase, oCunhadaEN, id);
oDatabase.ConnectionClose();
}
catch (Exception oException)
{
oDatabase.ConnectionClose();
throwoException;
}
returnoCunhadaEN;
}
public ListReadAll()
{
List cunhadaCollection =new List();
DatabaseoDatabase = oFacadeDAO.CreateInstanceDatabase();
try
{
oDatabase.ConnectionOpen(oFacadeDAO.GetStringConnection());
base.ReadAll(oDatabase, newCunhadaEN(this.oFacadeDAO), delegate(BaseEN itemBase){
cunhadaCollection.Add((CunhadaEN)itemBase);
});
oDatabase.ConnectionClose();
}
catch (Exception oException)
{
oDatabase.ConnectionClose();
throwoException;
}
returncunhadaCollection;
}
}
}
Aqui é estrutura de uma classe DAO que tem filhos.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Persistencia.DAO.Base;
using Persistencia.EN;
using Persistencia.EN.Interface;
using Persistencia.EN.Base;
using Persistencia.Data.Base;
namespace Persistencia.DAO
{
class EsposaDAO : BaseDAO
{
private FacadeDAO oFacadeDAO;
publicEsposaDAO(FacadeDAO oFacadeDAO)
{
this.oFacadeDAO =oFacadeDAO;
}
public void Write(IEsposaoEsposa)
{
DatabaseoDatabase = oFacadeDAO.CreateInstanceDatabase();
try
{
oDatabase.ConnectionOpen(oFacadeDAO.GetStringConnection());
oDatabase.BeginTransacTion();
base.Write(oDatabase, (EsposaEN)oEsposa);
if(oEsposa.FilhoCollection != null)
{
oEsposa.FilhoCollection.ForEach(delegate(IFilho oFilho){
base.Write(oDatabase, (FilhoEN)oFilho);
});
}
oDatabase.ComitTransacTion();
oDatabase.ConnectionClose();
}
catch (Exception oException)
{
oDatabase.RollBack();
oDatabase.ConnectionClose();
throwoException;
}
}
public IEsposa Read(longid)
{
EsposaENoEsposaEN = newEsposaEN(oFacadeDAO);
DatabaseoDatabase = oFacadeDAO.CreateInstanceDatabase();
try
{
oDatabase.ConnectionOpen(oFacadeDAO.GetStringConnection());
base.Read(oDatabase, oEsposaEN, id);
if(oEsposaEN != null&& oEsposaEN.Id!= 0)
{
oEsposaEN.FilhoCollection = readAllFilho(oDatabase, oEsposaEN);
oEsposaEN.SetStatus(StatusObject.Loaded);//Aqui estouforçando o status da classe para objeto carregado. Só acontece quando a classetem filhos.
}
else
{
oEsposaEN = null;
}
oDatabase.ConnectionClose();
}
catch (Exception oException)
{
oDatabase.ConnectionClose();
throwoException;
}
returnoEsposaEN;
}
public ListReadAll()
{
List esposaCollection =new List();
DatabaseoDatabase = oFacadeDAO.CreateInstanceDatabase();
try
{
oDatabase.ConnectionOpen(oFacadeDAO.GetStringConnection());
base.ReadAll(oDatabase, newEsposaEN(this.oFacadeDAO), delegate(BaseEN itemBase){
EsposaEN oEsposa = (EsposaEN)itemBase;
oEsposa.FilhoCollection = readAllFilho(oDatabase, oEsposa);
oEsposa.SetStatus(StatusObject.Loaded);//Aqui estouforçando o status da classe para objeto carregado. Só acontece quando a classetem filhos.
esposaCollection.Add(oEsposa);
});
oDatabase.ConnectionClose();
}
catch (Exception oException)
{
oDatabase.ConnectionClose();
throwoException;
}
returnesposaCollection;
}
private List readAllFilho(DatabaseoDatabase, EsposaEN oEsposa)
{
List filhoCollection =new List();
base.ReadAllParent(oDatabase, newFilhoEN(this.oFacadeDAO), oEsposa.Id,delegate(BaseENitemBase){
FilhoEN oFilho =(FilhoEN)itemBase;
oFilho.oEsposa =oEsposa;
filhoCollection.Add(oFilho);
});
returnfilhoCollection;
}
}
}
Como reflection não precisamos criar os comandos Sql e nem precisamos ficar programando para preencher as propriedades da classe.
Até o próximo artigo.