39
1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET de la aplicación con el mismo nombre, vista en la primera parte de la asignatura Casos de uso Registrar usuario Autenticarse Recuperar información de registro Actualizar información de registro Cambiar contraseña

MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

1

MiniPortal

Integración de SistemasDiseño e implementación con .NET

MiniPortal

Implementación en .NET de la aplicación con el mismo nombre, vista en la primera parte de la asignatura

Casos de usoRegistrar usuario

Autenticarse

Recuperar información de registro

Actualizar información de registro

Cambiar contraseña

Page 2: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

2

Estructura de paquetes del modeloEs.UDC.DotNet

Util

UserProfile

UserFacade

Exceptions

VO

Delegate

Model

MiniPortal

VO

DAO

Es.UDC.DotNet.MiniPortal.Model.UserProfile.VO

+UserProfileDetailsVO()+ToString() : String

+FirstName : String+Surname : String+Email : String+Language : String+Country : String

UserProfileDetailsVO

+UserProfileVO()+ToString()

+LoginName : String+EncryptedPassword : String+UserProfileDetailsVO : UserProfileDetailsVO

UserProfileVO

1

Ambas clases parametrizadas con el atributo [Serializable()]

Page 3: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

3

Patrón Value Object

Representa estado/valor

El estado se almacena en PropiedadesIncluyen métodos get y set implícitos

Sobrescribiremos (override) el método ToString()para imprimir el estado

VOs deben ser objetos serializablesSe indica con el atributo [Serializable()] precediendo a la declaración de la clase

Usaremos la notación xxxVO

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO

Page 4: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

4

Patrón Data Access Object

Oculta cómo se hace el acceso a la BD

Sus métodos necesitan recibirLa conexión (DbConnection)

Para crear los comandos a partir de ella

command = connection.CreateCommand()

La transacción (DbTransaction)Si hay una transacción iniciada, los comandos deben añadirse a ella (obligatoriamente)

/* If transaction exists, command will be added */if (transaction != null) {

command.Transaction = transaction;}

Patrón Data Access Object

IUserProfileDAO (Adapter)Define una interfaz para insertar, borrar, actualizar y encontrar UserProfileVOs

Permite implementar adaptadores para distintas BD (dialectos de SQL)

UserProfileDAOFactory (Factory)Permite obtener una instancia de un adaptador apropiado para la aplicación

Page 5: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

5

Patrón Data Access Object

IUserProfileDAO + UserProfileDAOFactoryEs posible hacer plug-n-play (sin recompilar) de adaptadores cuando se cambia de BD

Facilita la instalación/configuración de la aplicación

Usaremos la notación xxxDAOEl prefijo SQL en el entorno .NET se usa para hacer referencia aSQL Server, no para referirse a SQL estándarPara evitar confusiones, no utilizaremos el prefijo SQL (siempretrabajaremos con SQL estándar) y utilizaremos SQLServer para referirnos a la BD de Microsoft

Carga Dinámica de Clases

Implementación de Factorías

Clases que se desean instanciar puedenPertenecer al assembly activoEstar situadas en un assembly independiente (fichero .dll)

NamespacesSystem.Reflection

System.Runtime.Remoting

Page 6: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

6

Carga Dinámica de ClaseClase pertenece al assembly activo

// Nombre completo de la clase que se desea instanciarString daoClassName =

"Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.SQLServerUserProfileDAO";

// Recuperamos el assembly actualmente en ejecucionAssembly assembly = Assembly.GetExecutingAssembly();

// Creamos instancia del tipo especificado// Parametros: // * nombre del assembly en el que se define el tipo// * tipo que deseamos instanciarObject theObject = AppDomain.CurrentDomain.

CreateInstanceAndUnwrap(assembly.FullName, daoClassName);

return (IUserProfileDAO)theObject;

Carga Dinámica de ClaseClase pertenece al assembly independiente

// Nombre completo de la clase que se desea instanciarString className = "MySql.Data.MySqlClient.MySqlConnection";

// Nombre de la libreria en la que esta definida la claseString driverFile =

"c:\\MySQL Connector Net 1.0.9\\Binaries\\.NET 1.1\\MySql.Data.dll";

// Cargamos el assembly a partir de su nombreAssembly assembly = Assembly.LoadFrom(driverFile);

// Creamos instancia tipo especificado// Parametros: // * nombre del assembly en el que se define el tipo// * tipo que deseamos instanciarObject obj = AppDomain.CurrentDomain.

CreateInstanceAndUnwrap(assembly.FullName, className);

return (DbConnection) obj;

Page 7: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

7

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.UserProfileDAOFactory

public sealed class UserProfileDAOFactory {

/* NOTE: constants are implicitly static */private const String DAO_CLASS_NAME_PARAMETER =

"UserProfileDAOFactory/daoClassName";

/* NOTE: Class constructor must be private, so nobody will* be allowed to instantiate it */private UserProfileDAOFactory() { }

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.UserProfileDAOFactory

/// <exception cref="ConfigurationParameterException"/> /// <exception cref="InternalErrorException"/> public static IUserProfileDAO GetDAO() {

try {String daoClassName = ConfigurationManager.

AppSettings[DAO_CLASS_NAME_PARAMETER];

Assembly assembly = Assembly.GetExecutingAssembly();

Object theObject = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assembly.FullName, daoClassName);

return (IUserProfileDAO)theObject;

} catch (Exception e) {throw new InternalErrorException(e);

}}

}

Page 8: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

8

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.UserProfileDAOFactory

Ejemplo de uso

DbProviderFactory dbFactory = DbProviderFactories.GetFactory(providerInvariantName);

/* Create and open the connection */connection = dbFactory.CreateConnection();connection.ConnectionString = connectionString;connection.Open();

/* Get DAO */IUserProfileDAO dao = UserProfileDAOFactory.GetDAO();

/* Test DAO.Exists */Boolean userExist = dao.Exists(connection, transaction,

userProfileVO.LoginName);

Es.UDC.DotNet.Util

Es.UDC.DotNet

Exceptions

Log

Crypto

MiniPortal

Util

Page 9: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

9

Es.UDC.DotNet.Util.Exceptions

Es.UDC.DotNet.Util.Exceptions

InternalErrorException

Error grave durante la ejecución de un métodoCaída de la BD, carga errónea de clases, etc.

Oculta el API empleada en la implementación

Encapsula la excepción real que se ha producidoÚtil para depuración

ModelException

Errores Lógicos en el modelo

Page 10: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

10

Es.UDC.DotNet.Util.Exceptionsusing System;

namespace Es.UDC.DotNet.Util.Exceptions {

public class InternalErrorException : Exception {

private Exception encapsulatedException = null;

public InternalErrorException(Exception exception) {encapsulatedException = exception;

}

public InternalErrorException(String msg) : base(msg) { }

Es.UDC.DotNet.Util.Exceptions

#region Properties Region

public override String Message{get { if (encapsulatedException == null)

return this.Message; else

encapsulatedException.Message;}

}

public Exception EncapsulatedException {get { return encapsulatedException; }

}

#endregion}

}

Page 11: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

11

Es.UDC.DotNet.Util.Exceptionsusing System;

namespace Es.UDC.DotNet.Util.Exceptions {

public class InstanceException : ModelException {

private Object key;private String className;

protected InstanceException(String specificMessage, Object key, String className): base(specificMessage + " (key = '" + key +

"' - className = '" + className + "')") {

this.key = key;this.className = className;

}

Es.UDC.DotNet.Util.Exceptions

#region Properties

public Object Key {get { return key; }

}

public String ClassName {get { return className; }

}

#endregion

}

}

Page 12: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

12

Es.UDC.DotNet.Util.LogProporciona log de mensajes a pantalla y/o fichero

Contenido:LogManager.cs

App.config: parámetros de configuraciónLogDestination: destino de los mensajes (SCREEN / FILE / ALL)SeverityLevel: tipo de mensajes de los que se hará log (INFO / WARNING / ERROR)FileLocation: ruta al fichero de logFilePartialName y FileExtension: nombre del fichero de log con la sintaxis:

{FilePartialName}_DATE.{FileExtension}

Ejemplo de uso:

LogManager.RecordMessage("Example Message", LogManager.MessageType.INFO, this);

Resultado:

[13/11/2006 17:26:56] Es.UDC.DotNet.MiniPortal.Model.UserProfile.VO: INFO: Example Message

Sustituto de Console.WriteLine("…")

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

Page 13: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

13

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

AbstractUserProfileDAO

Implementación de IUserProfileDAO independiente del Data Provider

Deja sin implementar los métodos: String GetParameterSyntax(String parameterName)

String GetParameterName(String parameterName)

SQLServerUserProfileDAO, OracleUserProfileDAO, MySQLUserProfileDAO, etc.

Implementaciones para un Data Provider específico

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

public abstract class AbstractUserProfileDAO : IUserProfileDAO {

#region IUserProfileDAO Members

/// <summary>/// Create a new <code>UserProfile</code>/// </summary>/// <exception cref="DuplicateInstanceException"/> /// <exception cref="InternalErrorException"/> public void Create(DbConnection connection, DbTransaction transaction,

UserProfileVO userProfileVO) {

/* Check if the user already exists. */if (Exists(connection, transaction, userProfileVO.LoginName)) {

throw new DuplicateInstanceException(userProfileVO.LoginName, typeof(UserProfileVO).FullName);

}

Page 14: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

14

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

try {/* Create the command. */DbCommand command = connection.CreateCommand();

/* If transaction exists, command will be added */if (transaction != null) {

command.Transaction = transaction;}

command.CommandText ="INSERT INTO UserProfile (loginName, enPassword, " +

"firstName, surname, email, language, country) " +"VALUES (" + GetParameterSyntax("loginName") +

", " + GetParameterSyntax("enPassword") +", " + GetParameterSyntax("firstname") +", " + GetParameterSyntax("surname") +", " + GetParameterSyntax("email") +", " + GetParameterSyntax("language") +", " + GetParameterSyntax("country") + ")";

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

DbParameter loginNameParam = command.CreateParameter();loginNameParam.ParameterName = GetParameterName("loginName");loginNameParam.DbType = DbType.String;loginNameParam.Size = 30;loginNameParam.Value = userProfileVO.LoginName;command.Parameters.Add(loginNameParam);

DbParameter encryptedPasswordParam = command.CreateParameter();<< ... >>

DbParameter firstNameParam = command.CreateParameter();<< ... >>

DbParameter surnameParam = command.CreateParameter();<< ... >>

DbParameter emailParam = command.CreateParameter();<< ... >>

DbParameter languageParam = command.CreateParameter();<< ... >>

Page 15: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

15

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

DbParameter countryParam = command.CreateParameter();<< ... >>

command.Prepare();

int insertedRows = command.ExecuteNonQuery();

if (insertedRows == 0) {throw new SQLException("Can not add row to table" +

" 'UserProfile'");}

if (insertedRows > 1) {throw new SQLException("Duplicate row for login name = '" +

userProfileVO.LoginName + "' in table 'UserProfile'");}

} catch (SQLException e) { throw new InternalErrorException(e);

}} // Create

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

/// <summary>/// Looks if an <code>UserProfile</code> with/// this <paramref name="loginName"/> exists/// </summary>/// <returns>True if the <code>UserProfile</code> exists</returns>/// <exception cref="InternalErrorException"/> public Boolean Exists(DbConnection connection,

DbTransaction transaction, String loginName) {

DbDataReader dataReader = null;

try {/* Create the command. */

/* If transaction exists, command will be added */

command.CommandText ="SELECT loginName FROM UserProfile " +"WHERE loginName = " + GetParameterSyntax("loginName");

Page 16: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

16

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

DbParameter loginNameParam = command.CreateParameter();loginNameParam.ParameterName = GetParameterName("loginName");loginNameParam.DbType = DbType.String;loginNameParam.Value = loginName;loginNameParam.Size = 30;command.Parameters.Add(loginNameParam);

command.Prepare();

dataReader = command.ExecuteReader();

return (dataReader.Read());

} catch (SQLException e) { throw new InternalErrorException(e);

} finally {dataReader.Close();

}} // Exists

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

/// <exception cref="InstanceNotFoundException"/> /// <exception cref="InternalErrorException"/> public UserProfileVO Find(DbConnection connection,

DbTransaction transaction, String loginName) {

DbDataReader dataReader = null;

try {

/* Create the command. */

/* If transaction exists, command will be added */

command.CommandText ="SELECT enPassword, firstName, surname, email, " +

"language, country " +"FROM UserProfile " +"WHERE loginName = " + GetParameterSyntax("loginName");

Page 17: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

17

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

DbParameter loginNameParam = command.CreateParameter();loginNameParam.ParameterName = GetParameterName("loginName");loginNameParam.DbType = DbType.String;loginNameParam.Size = 30;loginNameParam.Value = loginName;command.Parameters.Add(loginNameParam);

command.Prepare();

dataReader = command.ExecuteReader();

if (!dataReader.Read()) {throw new InstanceNotFoundException(loginName,

typeof(UserProfileVO).FullName);}

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

String encryptedPassword = dataReader.GetString(0);String firstname = dataReader.GetString(1);String surname = dataReader.GetString(2);String email = dataReader.GetString(3);String language = dataReader.GetString(4);String country = dataReader.GetString(5);

UserProfileDetailsVO userProfileDetailsVO =new UserProfileDetailsVO(firstname,

surname, email, country, language);

/* Return the value object. */return new UserProfileVO(loginName, encryptedPassword,

userProfileDetailsVO);

} catch (DbException e) { throw new InternalErrorException(e);

} finally {dataReader.Close();

}} // Find

Page 18: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

18

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

/// <exception cref="InstanceNotFoundException"/> /// <exception cref="InternalErrorException"/> public void Update(DbConnection connection, DbTransaction transaction,

UserProfileVO userProfileVO) {

try {

/* Create the command. */

/* If transaction exists, command will be added */

command.CommandText ="UPDATE UserProfile " +"SET enPassword = " + GetParameterSyntax("enPassword") +

", firstName = " + GetParameterSyntax("firstname") +", surname = " + GetParameterSyntax("surname") +", email = " + GetParameterSyntax("email") +", language = " + GetParameterSyntax("language") +", country = " + GetParameterSyntax("country") +

" WHERE loginName = " + GetParameterSyntax("loginName");

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

DbParameter loginNameParam = command.CreateParameter();loginNameParam.ParameterName = GetParameterName("loginName");loginNameParam.DbType = DbType.String;loginNameParam.Size = 30;loginNameParam.Value = userProfileVO.LoginName;command.Parameters.Add(loginNameParam);

/* Crear el resto de parametros:* encryptedPasswordParam, firstNameParam, surnameParam,* emailParam, languageParam y countryParam*/

command.Prepare();

Page 19: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

19

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

int updatedRows = command.ExecuteNonQuery();

if (updatedRows == 0) {throw new InstanceNotFoundException(

userProfileVO.LoginName, typeof(UserProfileVO).FullName);

}

if (updatedRows > 1) {throw new SQLException("Duplicate row for login name = '" +

userProfileVO.LoginName + "' in table 'UserProfile'");}

} catch (DbException e) { throw new InternalErrorException(e);

}} // Update

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

/// <exception cref="InstanceNotFoundException"/> /// <exception cref="InternalErrorException"/> public void Remove(DbConnection connection,

DbTransaction transaction, String loginName) {

try {

/* Create the command. */

/* If transaction exists, command will be added. */

command.CommandText ="DELETE FROM UserProfile " +"WHERE loginName = " + GetParameterSyntax("loginName");

DbParameter loginNameParam = command.CreateParameter();loginNameParam.ParameterName = GetParameterName("loginName");loginNameParam.DbType = DbType.String;loginNameParam.Size = 30;loginNameParam.Value = loginName;command.Parameters.Add(loginNameParam);

Page 20: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

20

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.AbstractUserProfileDAO

command.Prepare();

int removedRows = command.ExecuteNonQuery();

if (removedRows == 0) {throw new InstanceNotFoundException(loginName,

typeof(UserProfileVO).FullName);}

} catch (DbException e) { throw new InternalErrorException(e);

}} // Remove

#endregion

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.SQLServerUserProfileDAO

Page 21: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

21

Es.UDC.DotNet.MiniPortal.Model.UserProfile.DAO.SQLServerUserProfileDAO

public class SQLServerUserProfileDAO : AbstractUserProfileDAO {

private const String SQL_SERVER_PARAM_PREFIX_PARAMETER ="UserProfileDAOFactory/parameterPrefix";

private static String PARAMETER_PREFIX =ConfigurationManager.AppSettings[SQL_SERVER_PARAM_PREFIX_PARAMETER];

protected override String GetParameterSyntax(string parameterName) {

return PARAMETER_PREFIX + parameterName;

}

protected override String GetParameterName(string parameterName) {

return PARAMETER_PREFIX + parameterName;}

}

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate

Page 22: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

22

Session Facade y Business Delegate

Patrón Session FacadeNotación XXXFacade

Patrón Business DelegateNotación XXXDelegate

En este caso, el objeto Business Delegate y el Session Facade serán el mismo

No necesitamos hacer plug-n-play del modeloEl Delegate será una clase concreta

Session Facade y Business Delegate

Para facilitar la comprensión del código, las operaciones del Session Facade se han implementado directamente

En una aplicación real, las operaciones del Session Facade deberían implementarse en términos de acciones (implementar cada operación en una clase)

Page 23: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

23

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

[Serializable()]public class UserFacadeDelegate {

private String loginName;

private const String PROVIDER_INVARIANT_NAME_PARAMETER ="UserProfileDAOFactory/providerInvariantName";

private const String CONNECTION_STRING_PARAMETER ="UserProfileDAOFactory/connectionString";

private static String providerInvariantName =ConfigurationManager.AppSettings[PROVIDER_INVARIANT_NAME_PARAMETER];

private static String connectionString =ConfigurationManager.AppSettings[CONNECTION_STRING_PARAMETER];

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

private static DbProviderFactory dbProviderFactory =DbProviderFactories.GetFactory(providerInvariantName);

/* State Facade */public UserFacadeDelegate() {

loginName = null;}

Page 24: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

24

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

/// <exception cref="InstanceNotFoundException">/// This error occurs when this <paramref name="loginName"/> does/// not exist./// </exception>/// <exception cref="IncorrectPasswordException">/// This error occurs when the <paramref name="password"/> does not/// match with the user password stored./// </exception>/// <exception cref="InternalErrorException"/> public LoginResultVO Login(String loginName, String password,

Boolean passwordIsEncrypted) {

DbConnection connection = null;String encryptedPassword = null;

try {

/* Create the connection. */connection = dbProviderFactory.CreateConnection();connection.ConnectionString = connectionString;connection.Open();

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

IUserProfileDAO dao = UserProfileDAOFactory.GetDAO();

UserProfileVO userProfileVO =dao.Find(connection, null, loginName);

if (passwordIsEncrypted) {encryptedPassword = password;

} else {encryptedPassword = Crypto.crypt(password);

}

if (!userProfileVO.EncryptedPassword.Equals(encryptedPassword)) {throw new IncorrectPasswordException(loginName);

}

this.loginName = loginName;return new LoginResultVO(userProfileVO.LoginName,

userProfileVO.EncryptedPassword,userProfileVO.UserProfileDetailsVO.Language,userProfileVO.UserProfileDetailsVO.Country);

Page 25: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

25

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

} catch (InstanceNotFoundException e) {throw e;

} catch (InternalErrorException e) {throw e;

} catch (Exception e) {throw new InternalErrorException(e);

} finally {try {

if (connection != null) {connection.Close();

}} catch (Exception e) {

throw new InternalErrorException(e);}

}} // Login

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

/// <exception cref="InternalErrorException"/> public UserProfileVO FindUserProfile() {

DbConnection connection = null;

try {

/* Create the connection. */<< ... >>

/* Get a DAO */<< ... >>

/* State Facade. loginName is stored. */return dao.Find(connection, null, this.loginName);

} catch (InstanceNotFoundException e) {throw new InternalErrorException(e);

} catch (InternalErrorException e) {throw e;

Page 26: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

26

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

} catch (Exception e) {throw new InternalErrorException(e);

} finally {try {

if (connection != null) {connection.Close();

}} catch (Exception e) {

throw new InternalErrorException(e);}

}} // FindUserProfile

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

/// <exception cref="DuplicateInstanceException">/// This error occurs when exists a previous instance with the same key./// </exception>/// <exception cref="InternalErrorException"/>public void RegisterUser(String loginName, String clearPassword,

UserProfileDetailsVO userProfileDetailsVO) {

DbConnection connection = null;DbTransaction transaction = null;Boolean rollback = false;

try {

/* Create the connection. */<< ... >>

/* Starts new transaction. */transaction =

connection.BeginTransaction(IsolationLevel.Serializable);

Page 27: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

27

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

IUserProfileDAO dao = UserProfileDAOFactory.GetDAO();

String encryptedPassword = Crypto.crypt(clearPassword);

UserProfileVO userProfileVO = new UserProfileVO(loginName,encryptedPassword, userProfileDetailsVO);

dao.Create(connection, transaction, userProfileVO);

this.loginName = loginName;

} catch (DuplicateInstanceException e) {rollback = true;throw e;

} catch (InternalErrorException e) {rollback = true;throw e;

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

} catch (Exception e) {rollback = true;throw new InternalErrorException(e);

} finally {try {

/* Commit or rollback, and finally, close connection. */if (connection != null) {

if (rollback) {transaction.Rollback();

} else {transaction.Commit();

}connection.Close();

}} catch (Exception e) {

throw new InternalErrorException(e);}

}} // RegisterUser

Page 28: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

28

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

/// <exception cref="InternalErrorException"/> public void UpdateUserProfileDetails(UserProfileDetailsVO

userProfileDetailsVO) {

<< ... >>

try {

/* Create the connection. */<< ... >>

/* Starts new transaction. */<< ... >>

/* Get a DAO */<< ... >>

UserProfileVO userProfileVO = dao.Find(connection,transaction, this.loginName);

userProfileVO.UserProfileDetailsVO = userProfileDetailsVO;

dao.Update(connection, transaction, userProfileVO);

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

} catch (InstanceNotFoundException e) {rollback = true;throw new InternalErrorException(e);

} catch (InternalErrorException e) {rollback = true;throw e;

} catch (Exception e) {rollback = true;throw new InternalErrorException(e);

} finally {try {

/* Commit or rollback, and finally, close connection. */<< ... >>

} catch (Exception e) {throw new InternalErrorException(e);

}}

} // UpdateUserProfileDetails

Page 29: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

29

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

/// <exception cref="IncorrectPasswordException">/// This error occurs when the <paramref name="oldClearPassword"/> does/// not match with the user's password stored./// </exception>/// <exception cref="InternalErrorException"/> public void ChangePassword(String oldClearPassword,

String newClearPassword) {

<< ... >>

try {/* Create the connection. */

<< ... >>/* Starts new transaction. */

<< ... >>/* Get a DAO */

<< ... >>

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

UserProfileVO userProfileVO = dao.Find(connection,transaction, this.loginName);

/* Recovery current password. */String storedPassword = userProfileVO.EncryptedPassword;

/* Compare current with oldClearPassword. */if (!storedPassword.Equals(Crypto.crypt(oldClearPassword))) {

throw new IncorrectPasswordException(this.loginName);}

/* Update current password. */storedPassword = Crypto.crypt(newClearPassword);

userProfileVO.EncryptedPassword = storedPassword;

dao.Update(connection, transaction, userProfileVO);

Page 30: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

30

Es.UDC.DotNet.MiniPortal.Model.UserFacade.Delegate.UserFacadeDelegate

} catch (InstanceNotFoundException e) {rollback = true;throw new InternalErrorException(e);

} catch (InternalErrorException e) {rollback = true;throw e;

} catch (Exception e) {rollback = true;throw new InternalErrorException(e);

} finally {try {

/* Commit or rollback, and finally, close connection. */<< ... >>

} catch (Exception e) {throw new InternalErrorException(e);

}}

} // ChangePassword

Pruebas de unidad

Se han incluido pruebas de unidad para validar clases individuales

Incluyen un método Main (comentado con //) con código de prueba dentro de

#region Test Code Region. Uncomment for testing.

#endregion

Las pruebas de unidad de los DAOs se han ubicado en la factoría de DAOs

El Session Facade contiene código de prueba para cada caso de uso

Page 31: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

31

Acceso a Parámetros Configurables

App.configFichero que permite almacenar propiedades configurables

Almacena pares (variable/valor)

Formato XML

Accesible en tiempo de ejecución

Acceso a parámetros no definidos implica que se lance ConfigurationErrorException

Aplicaciones Web ASP.NETLectura de propiedades desde un fichero Web.config

Acceso a Parámetros ConfigurablesEjemplo de fichero App.config

<?xml version="1.0" encoding="utf-8" ?><configuration>

<appSettings>

<!-- ****** Parameters for DataBase Connection ******** --><!-- Data Provider --><add key="UserProfileDAOFactory/providerInvariantName"

value="System.Data.SqlClient"/>

<!-- Connection String --><add key="UserProfileDAOFactory/connectionString"

value="Data Source=localhost\SQLExpress; Initial Catalog=miniportal; User ID=user; Password=password"/>

</appSettings>

</configuration>

Page 32: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

32

Acceso a Parámetros ConfigurablesEjemplo de acceso

using System.Configuration;

try {

// Gets the AppSettings section for the current applicattion’s// default configuration and access to the parameter by keyString connectionString =

ConfigurationSettings.AppSettings[“UserProfileDAOFactory/connectionString”];

<< ... >>

} catch(ConfigurationErrorException e) {

Console.WriteLine(“Parameter not found”);}

Es.UDC.DotNet.PageByPageIterator

Patrón Page-by-Page IteratorSolicitar objetos por bloques

En JavaResultSet.TYPE_SCROLL_INSENSITIVE

Permite mover el cursor hacia adelante, atrás o saltar a una posición absoluta o relativaNo muestra los cambios que se estén haciendo a la BD mientras está abierto

En .NETNo se dispone de un equivalente al ResultSet.TYPE_SCROLL_INSENSITIVE

Page 33: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

33

Es.UDC.DotNet.PageByPageIteratorpublic List<UserProfileVO> Find(DbConnection connection,

DbTransaction transaction, String condition, String orderField, int startIndex, int count) {

List<UserProfileVO> info = new List<UserProfileVO>();

try { String commandText =

" Select top " + count + " * from UserProfile " +" where " + condition + " and " + orderField + " not in " + " (select top " + startIndex + " " + orderField +" from UserProfile where " + condition +" order by " + orderField + ") " +" order by " + orderField + ";";

DbCommand command = connection.CreateCommand();command.Transaction = transaction;command.CommandText = commandText;command.Prepare();DbDataReader dr = command.ExecuteReader();

Es.UDC.DotNet.PageByPageIteratorwhile (dr.Read()) {

String loginName = dr.GetString(0);String encryptedPassword = dr.GetString(1);String firstName = dr.GetString(2);String surname = dr.GetString(3);String email = dr.GetString(4);String language = dr.GetString(5);String country = dr.GetString(6);

UserProfileDetailsVO userProfileDetailsVO =new UserProfileDetailsVO(firstName, surname, email, language, country);

UserProfileVO userProfileVO =new UserProfileVO(loginName, encryptedPassword, userProfileDetailsVO);

info.Add(userProfileVO);

dr.Close();}

} catch(DbException e) { <<...>>> }

return info;}

Page 34: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

34

Es.UDC.DotNet.PageByPageIterator#region Test Code Region. Uncomment for testing.

public static void Main(String[] args) {

int startIndex = 0;int count = 25;String orderField = "loginName";String condition = "language='ES'";

Boolean end = false;

// Get Connection<<...>>

while (!end) {

List<UserProfileVO> info = Find(connection, transaction, condition, orderField,

startIndex, count);

foreach (UserProfileVO userProfile in info) {Console.WriteLine(userProfile);

}

Es.UDC.DotNet.PageByPageIterator

Console.WriteLine("--------------------------");

if (info.Count < count)end = true;

elsestartIndex = startIndex + count;

info.Close();

}

Console.ReadLine();

} // Main

#endregion

Page 35: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

35

Es.UDC.DotNet.PageByPageIterator

Otras soluciones:Usando DataSet

DbDataAdapter – Método Fill(DataSet, Int32, Int32, String)adapter.Fill(dataSet, startIndex, count, "Users");

InconvenienteEficiencia reducida

Usando DataReaderDr.Read()

Solución más eficiente que usando un DataSetInconveniente

Necesario recorrer todas las filas previas a startIndex

Generación de IdentificadoresBasado en Columnas Contador

Inserción de cada fila implica la creación automática de un valor numérico empleado como identificador

Una vez insertada la fila, puede consultarse el último identificador creado mediante una query

Query dependiente del SGBD

MS SQL Serverselect @@identity

MySQLselect LAST_INSERT_ID()

Page 36: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

36

Generación Identificadores

<<implements>>

Generación IdentificadoresIEntityIdentifierRetrieverusing System;using System.Data.Common;

namespace IdentifierGenerator {

interface IEntityIdentifierRetriever {

/// <summary>/// Returns the last Entity Identifier generated/// </summary>Int64 GetGeneratedIdentifier(DbConnection connection);

}}

Page 37: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

37

Generación IdentificadoresGenericEntityIdentifierRetriever (I)using System;using System.Data;using System.Data.Common;using System.Configuration;

using Es.UDC.DotNet.Util.Exceptions;

namespace IdentifierGenerator {

public class GenericEntityIdentifierRetriever : IEntityIdentifierRetriever {

private const String QUERY_PARAMETER ="GenericEntityIdentifierRetriever/query";

private static String queryString =ConfigurationManager.AppSettings[QUERY_PARAMETER];

Generación IdentificadoresGenericEntityIdentifierRetriever (II)

/// <summary>/// Returns the last Entity Identifier generated/// </summary>/// <param name="connection">DataBase Connection</param>/// <exception cref="InternalErrorException"/> public Int64 GetGeneratedIdentifier(DbConnection connection) {

DbCommand command = null;

try {command = connection.CreateCommand();command.CommandText = queryString;

Int64 identity = Convert.ToInt64(command.ExecuteScalar());return identity;

} catch (Exception e) {throw new InternalErrorException(e);

}}

}}

Page 38: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

38

Generación IdentificadoresEntityIdentifierRetrieverFactoryclass EntityIdentifierRetrieverFactory {

private const String RETRIEVER_CLASS_NAME_PARAMETER ="EntityIdentifierRetrieverFactory/retrieverClassName";

private EntityIdentifierRetrieverFactory() { }

public static IEntityIdentifierRetriever GetRetriever() {

Object theObject = null;

try {

String retrieverClassName =ConfigurationManager.AppSettings[RETRIEVER_CLASS_NAME_PARAMETER];

Assembly assembly = Assembly.GetExecutingAssembly();

theObject = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assembly.FullName, retrieverClassName);

} catch (Exception e) {throw new InternalErrorException(e);

}

return (IEntityIdentifierRetriever)theObject;}

}

Generación IdentificadoresParámetros de configuración

Query para la obtención del último identificador insertado

<add key="GenericEntityIdentifierRetriever/query"

value="SELECT @@IDENTITY"/>

Clase instanciada por la factoría EntityIdentifierRetrieverFactory para la recuperación de identificadores

<add key="EntityIdentifierRetrieverFactory/retrieverClassName“

value="IdentifierGenerator.GenericEntityIdentifierRetriever"/>

Page 39: MiniPortal - UDCsabia.tic.udc.es/.../transparencias/04-MiniPortal.pdf · 1 MiniPortal Integración de Sistemas Diseño e implementación con .NET MiniPortal Implementación en .NET

39

Generación IdentificadoresEjemplo de uso: MiniBank (I)public class CCAccountDAO : AbstractAccountDAO {

/// <summary>/// Implements the Create operation for AccountDAO using a Counter Columns approach/// </summary>/// <exception cref="InternalErrorException"/> public AccountVO Create(DbConnection connection, Transaction transaction, AccountVO accountVO) {

DbCommand command = null;

try {command = connection.CreateCommand();command.CommandText = "INSERT INTO Account (userID, balance) " +

" values (" + GetParameterSyntax(userID) + ", " + GetParameterSyntax(balance) + ")";

// paramaters configuration <<…>>

command.Prepare();

/* Execute query. */int insertedRows = command.ExecuteNonQuery();

if (insertedRows == 0) throw new SQLException("Can not add row to table 'Account'");

if (insertedRows > 1)throw new SQLException("Duplicate row in table 'Account'");

Generación IdentificadoresEjemplo de uso: MiniBank (II)

/* Get account identifier. */IEntityIdentifierRetriever entityIdentifierRetriever =

EntityIdentifierRetrieverFactory.GetRetriever();

Int64 accountIdentifier = entityIdentifierRetriever.GetGeneratedIdentifier(connection);

/* Return the value object AccountVO(id, userID, balance) */return new AccountVO(accountIdentifier, accountVO.UserIdentifier,

accountVO.Balance);

} catch(Exception e) {throw new InternalErrorException(e);

}}

}