ADO.Net DataServices facilita el desarrollo N-Tier de aplicaciones que se apoyen en ADO.Net Entity Framework, exponiendo una fachada de servicios CRUD que mediante una interface REST muy sencilla de usar. Para mayor comodidad dispone de librerías cliente para llamar a esa interfaz y consultarla mediante LINQ.
Los programadores pueden extender la funcionalidad básica del servicio mediante métodos interceptores, como el siguiente, en el que validamos o completamos la entidad antes de la operación :
[ChangeInterceptor("Fichas")]
public void OnChangeFichas(Ficha ficha, UpdateOperations action)
{
try
{
switch (action)
{
case UpdateOperations.Add:
Logic.Fichas.Validate(ficha);
ficha.IdFicha = Logic.Fichas.GetNewGUID();
break;
case UpdateOperations.Change:
Logic.Fichas.Validate(ficha);
break;
}
}
catch(Exception ex)
{
throw new DataServiceException("No se ha podido realizar la operacion", ex);
}
}
Esto puede ser suficiente en muchos casos, pero también tiene limitaciones. Al ser métodos sin valor de retorno nos dificulta la obtención del estado del objeto posterior a la ejecución, por ejemplo no dispondríamos del GUID en el cliente. Además este interceptor se ejecuta antes de la operación y no ofrece ningún evento a posteriori, esto impide llamar a lógicas de negocio en el servidor que se ejecuten transaccionalmente con la operación o después de esta.
Por el contrario los servicios WCF ofrecen flexibilidad total tanto en funcionalidad como en infraestructura, a costa de un poco más de código y una configuración mas tediosa.
El ejemplo anterior puede resolverse con los siguientes métodos:
public Ficha AddFicha(Ficha ficha)
{
try
{
Logic.Fichas.Validate(ficha);
ficha.IdFicha = Logic.Fichas.GetNewGUID();
using (var context = new Context())
{
context.Attach(ficha);
context.SaveChanges();
}
return ficha;
}
catch (Exception ex)
{
Log.Excepcion(ex);
throw new FaultException("No se ha podido agregar la ficha por " + ex.Message);
}
}
Para actualizar entidades se usa un método extensor que asegure que la entidad inicialmente desatachada se persista en base de datos, según explica Cesar De La Torre en su blog
public Ficha UpdateFicha(Ficha ficha)
{
try
{
Logic.Fichas.Validate(ficha);
using (var context = new Context())
{
context.Attach(ficha);
ficha.SetAllModified(context);
using (var transaction = context.Connection.BeginTransaction())
{
context.SaveChanges();
Logic.Fichas.PostProcess(ficha);
transaction.Commit();
}
}
return ficha;
}
catch (Exception ex)
{
Log.Excepcion(ex);
throw new FaultException("No se ha podido actualizar la ficha por " + ex.Message);
}
}
En fin, una vez mas .Net ofrece alternativas para un mismo fin y depende de las circunstancias el elegir la más directa o la más flexible.
Agradecimiento especial a los consultores de Plain Concepts cuyos conocimientos sobre arquitectura de software y tecnologías Microsoft son apabullantes. Espero vuestros comentarios.