En este artículo vamos a ver cómo usar WCF Data Services
para interactuar con nuestra base de datos mediante REST, para esto vamos a
realizar un formulario de CRUD básico y seguiremos los siguientes pasos:
1.
Crear aplicación Asp.net
2.
Crear modelo de datos con Entity Framework
4.
Configurar WCF Data Service para acceso a
nuestras entidades.
5.
Interactuar con nuestro servicio desde una aplicación
asp.net
¿Qué es WCF Data
Services?
También conocido como ADO.NET data services, es un
componente del .net Framework que permite crear servicios web usando ODATA (Open Data Protocol), para
exponer y consumir datos en la web mediante REST, ODATA expone los datos como recursos que son accesibles y
modificados a través de URIs, usando los verbos HTTP GET(Consultar), PUT(Modificar),
POST(Ingresar) y DELETE(Eliminar).
Creando nuestro modelo de datos con la DB ejemplo Northwind.
Antes que nada para crear el modelo debemos tener la base de
datos Northwind en nuestra instancia de SQl Server, dichas base de datos se
adjunta en este artículo para que se sea descargada y restaurada. Una vez
tengamos esta DB, en nuestro proyecto web hacemos click derecho, agregar un
nuevo elemento y seleccionamos, ADO:NET Entity Data Model.
Luego configuramos la conexión con la base de datos:
Y seleccionamos las tablas que necesitemos de nuestra base
de datos.
Creando nuestro WCF Data Service.
Ahora que tenemos creado nuestro modelos de datos,
procedemos a crear nuestro servicio de datos, para esto hacemos clic derecho,
agregar nuevo elemento, y elegimos Servicio de datos WCF.
Enseguida nos crea nuestro Data service, y nos indica que
debemos especificar el origen de datos y configurar los permisos para las
entidades que vamos a exponer en el servicio.
public class WcfDataService1 : DataService<
/* TODO: escriba aquí el nombre de clase del origen
de datos */ >
{
// Se llama a este método una única vez para
inicializar directivas aplicables a todo el ámbito del servicio.
public static void InitializeService(DataServiceConfiguration
config)
{
// TODO: establezca reglas para indicar qué operaciones de
servicio y conjuntos de entidades son visibles, actualizables, etc.
// Ejemplos:
//
config.SetEntitySetAccessRule("MiConjuntoDeEntidades",
EntitySetRights.AllRead);
// config.SetServiceOperationAccessRule("MiOperaciónDeServicio",
ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion
= DataServiceProtocolVersion.V2;
}
}
En nuestro caso el origen
de datos es NorthwindEntities
que hace referencia al modelo que creamos con entity Framework, y vamos a
especificar permisos de crear, leer, actualizar y eliminar datos en la tabla Customers de nuestra DB, la
configuración del servicio nos queda así:
public
class NorttwindAccess
: DataService<NorthwindEntities>
{
// Se llama a este método una única vez para
inicializar directivas aplicables a todo el ámbito del servicio.
public static void InitializeService(DataServiceConfiguration
config)
{
// TODO: establezca reglas para indicar qué operaciones de
servicio y conjuntos de entidades son visibles, actualizables, etc.
// Ejemplos:
//
config.SetEntitySetAccessRule("MiConjuntoDeEntidades",
EntitySetRights.AllRead);
// config.SetServiceOperationAccessRule("MiOperaciónDeServicio",
ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion
= DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("Customers",
EntitySetRights.All);
config.UseVerboseErrors = true;
}
}
Cabe resaltar la
configuración de UseVerboseErrors en True, esto para lograr obtener el detalle
completo de la excepción desde el web services, en caso de que ocurra algún
error.
Ahora tenemos
configurado nuestro servicio de datos, lo podemos probar ingresando a la
URL http://localhost:1995/NorttwindAccess.svc
donde NorttwindAccess es el nombre
de nuestro servicio.
Nos muestra las tablas a
la cuales otorgamos permisos, en este caso solo la tabla Customeres.
También podemos hacer
cualquier query a través de la URI de nuestro servicio, algunos ejemplos a
continuación:
·
Seleccionar todos los registros de la tabla
Customers:
·
Seleccionar los registros donde el Campo
CustomerID sea igual a “ALFKI”:
·
Seleccionar todos los registros de la tabla
Customers ordenados por el campo ContactNAme:
·
Seleccionar todos los registros de la tabla
Customers donde el campo ContactName termine en “no”:
http://localhost:1995/NorttwindAccess.svc/Customers?$filter=endswith(ContactName,
'no')
·
Seleccionar los campos CustomerID y ContactName
de la tabla Customers:
Estos son algunos ejemplos de los tantos que se pueden
hacer.
Ahora procedemos a
referenciar nuestro nuevo servicio de datos a nuestra aplicación web asp.net,
para poder interactuar con él.
Una vez tenemos nuestro
servicio de datos referenciado podemos interactuar con el desde nuestra
aplicación.
En nuestro ejemplo vamos
a crear un CRUD básico para la tabla Customers, visualmente es de la siguiente
forma:
Para poblar el GridView
con todos los Clientes, creamos el siguiente método el cual será invocado en el
evento Load de nuestra página.
private
void LlenarGrid()
{
var serv = new NorthwindService.NorthwindEntities(new Uri("http://localhost:1995/NorttwindAccess.svc"));
var
clientes = (from c in
serv.Customers
orderby
c.ContactName
select
c).ToList();
this.gvCustomers.DataSource
= clientes;
this.gvCustomers.DataBind();
}
Observemos que
inicializamos nuestro modelo de datos a partir de nuestro servicios de datos, y
sobre el podemos ejecutar cualquier consulta linq to entities, en este caso obtenemos
todos los registros de la tabla
Customers y cargamos el GridView con los resultados.
Ahora para eliminar un
registro de la tabla Customers, en el vento gvCustomers_RowDeleting
De nuestro gridView
asignamos el siguiente fragmento de código:
try
{
string strID = this.gvCustomers.Rows[e.RowIndex].Cells[0].Text;
var serv = new NorthwindService.NorthwindEntities(new Uri("http://localhost:1995/NorttwindAccess.svc"));
NorthwindService.Customers eliminarCliente = (from
c in serv.Customers
where c.CustomerID.Equals(strID)
select
c).Single();
serv.DeleteObject(eliminarCliente);
serv.SaveChanges();
this.lblError.Text = "El
cliente se elimino correctamente.";
this.LlenarGrid();
}
catch (Exception ex)
{
this.lblError.Text
= string.Format("Ocurrió
un error al eliminar el cliete: {0}", ex.Message);
}
Para terminar con
nuestro ejemplo, vamos a observar el código alojado en el evento click del
botón guardar, en el cual se ejecutan las inserciones y actualizaciones a
nuestra DB:
try
{
var serv = new NorthwindService.NorthwindEntities(new Uri("http://localhost:1995/NorttwindAccess.svc"));
if (this.hfAccion.Value.Equals("Nuevo"))
{
NorthwindService.Customers
customer = new NorthwindService.Customers
{
CustomerID
= this.txtID.Text,
ContactName = this.txtNombre.Text,
CompanyName = this.txtCompania.Text
};
serv.AddToCustomers(customer);
}
else
{
NorthwindService.Customers
modificarCustomer =
(from c in serv.Customers
where
c.CustomerID.Equals(this.txtID.Text)
select
c).Single();
modificarCustomer.ContactName = this.txtNombre.Text;
modificarCustomer.CompanyName = this.txtCompania.Text;
serv.UpdateObject(modificarCustomer);
}
serv.SaveChanges();
this.lblError.Text = "El
cliente se actualizó correctamente.";
this.hfAccion.Value
= "Nuevo";
this.txtID.Enabled
= true;
this.LlenarGrid();
}
catch (Exception ex)
{
this.lblError.Text
= string.Format("Ocurrió
un error al ingresar el cliete: {0}", ex.Message);
}
Con esto doy por
terminado el artículo, espero que sea de gran utilidad para muchos, adicional
el link de los fuentes de la solución y el .bak de la base de datos a continuación. En un próximo
artículo estaré mostrando como consumir estos Data Services mediante Jquery a través de una petición AJAX.
Saludos.
Tavo, Me alegra enormemente que hagás artículos de tan alta talla.
ResponderEliminarUn abrazo y siga adelante con este excelente proyecto.
Gracias mi bro!!!
EliminarGracias, este artículo es justo lo que necesitaba!
ResponderEliminarJuan gracias a ti por leerlo, me alegra que te haya servido!!
EliminarHola, necesito de vuestra orientación a una problemática que tenemos y que paso s explicar:
ResponderEliminarTenemos un wcf operando con un solo método donde este posee la cadena de string que requiere una tabla ser actualizada o bien insertada. Sin embargo nos solicitaron cambiar el método, en este caso que sea una tabla y no la cadena de string y también devolver el nro de registros actualizado/insertado de la tabla con su respectivo estado ok
Gracias
Hola Arturo, según entiendo no estás usando WCF DataServices, si no un servicio WCF que tu construiste que no usa el protocolo OData, y ese servicio tiene un método que tiene una cadena de query ("INSERT INTO ...") para insertar o actualizar un dato según la necesidad, y te pidieron que no uses una cadena de string si no que uses otro mecanismo para insertar me imagino, sin embargo aun me cuesta un poco entender aun cuál es tu problema, por favor copia el código que usas actualmente y con eso te podré ayudar con mayor facilidad.
EliminarSaludos!
Hola Gustavo. Me han encargado realizar una aplicacion winform para que trabaje con una base de datos sql server instalada en un servidor de internet. ¿ Podria hacerlo mediante WCF ? y si es asi me podria indicar donde podria encontrar informacion al respecto.
ResponderEliminarGracias
Hola amigo, si, puedes hacerlo a través de WCF Data Services, puedes exponer la base de datos Sql Server, como explico en este artículo, de esta forma podrás interactuar con ella a través de http, ya que la base de datos queda expuesta a través de servicios REST, este sería el primer paso, y luego desde la aplicación WinForm, puedes usar un WebClient, para consumir los servicios, es bastante sencillo, observa este ejemplo donde consumen unos servicios REST en WCF desde una aplicación WPF, en tu caso sería igual:
Eliminarhttp://www.c-sharpcorner.com/UploadFile/rahul4_saxena/create-and-consume-wcf-restful-service/
Espero te sirva, saludos!
Hola Gustavo, el tuto esta genial.
ResponderEliminarUna consulta yo tengo una aplicacion WCF el cual la implementacion del [OperationContract] hace referencia a la capa de Bussiness Logic esta capa a su vez hace referencia a la Capa de Datos al momento de ejecutar el WCFTestClient mediante el IIS virtual la data de la BD se actualiza. El problema es que cuando lo subi al IIS Real y creo Clientes Reales desde Java me reconoce el Servicio lo que pasa es que no Accede a la Base de Datos, a que se debe eso?
Hola Christian, gracias por tu comentario, desde tu aplicación Java te reconoce bien el servicio? si es así pues pienso que puede estar ocurriendo un error al momento de almacenar los datos, es decir que desde la aplicación Java se este enviando mal algún parámetro y por eso genera error, te recomiendo depurar paso a paso desde tu aplicación Java así podrás ver que error genera en caso de que sea así, o también puedes habilitar el trace del servicio para monitorear mejor, cualquier cosa adicional que te pueda ayudar no dudes en escribir y si encuentras mayor detalle del error te podrá ayudar.
Eliminarsaludos!
Excelente el articulo que brindas, tengo una consulta al respecto del WCF al momento de su utilizacion que seria lo adecuado crear WSDL por cada entidad que tiene el sistema ejemplo ClienteService un WSDL en el cual por lo general lleve los contratos CRUD como indicas o un solo WSDL que se denomine por ejemplo ErpService y que contenga todos los Metodos que interactuen con todas las Entidades existentes del sistema. Saludos
ResponderEliminarHola José, si usas WCF DataServices no se trabaja con WSDL, dado que este usa REST para exponer directamente la base de datos, solo hospedas el servicio y accedes a través de su URL, de igual forma a través de la URL interactuas con la base de datos a través de ODATA, como muestro en el ejemplo, lo que si puedes hacer es otorgar diferentes permisos de acceso a entidades en específico o a todas las entidades, saludos!
Eliminar