2011-03-29 22 views
5

Recientemente tuve un poco de shock al pensar en combinar una arquitectura orientada a servicios con una interfaz de usuario brillante que aprovecha SQL para optimizar el rendimiento al consultar datos.Consultando servicios web con SQL

La vista de cuadrícula DevExpress para ASP.NET, por ejemplo, es tan genial que delega toda la lógica de filtrado, clasificación y paginación en el servidor de la base de datos. Pero esto supone que los datos son recuperados de un servidor de base de datos con capacidad SQL.

¿Qué sucede si quiero introducir una capa de servicio web entre la base de datos y las capas de la interfaz de usuario, y que la interfaz de usuario use los servicios web para consultar los datos?

  • ¿Cómo puedo diseñar los servicios web y la interfaz de usuario para que pueda pasar las solicitudes de filtrado desde la interfaz de usuario a través de los servicios web a la base de datos?
  • ¿Necesito proporcionar un servicio web de estilo List QueryData(string sqlQuery) y tener que analizar la cadena SQL por mi cuenta para garantizar la seguridad/restricción de acceso?
  • ¿O hay algún buen marco o directriz de diseño que me quite esta carga?

Esto debe ser un problema muy común, y estoy seguro de que ya se ha resuelto de manera relativamente adecuada, ¿o sí?

Estoy interesado principalmente en una solución compatible con .NET/C#.

Editar: He encontrado OData y Microsoft WCF Data Services. Si lo hizo bien, una aplicación basada en OData podría ser como sigue:

  1. usuario ---/Dadme página 1 (registros 1..10)/--->servidor ASP.NET control de (por supuesto, a través de HTTP)
  2. control de servidor ASP.NET ---/LINQ consulta/--->servicio de datos de clientes
  3. cliente de servicios de datos ---/OData consulta/--->WCF Data Service
  4. WCF Service Data ---/LINQ Consulta/--->Marco de la entidad
  5. Entity Framework ---/consultas SQL/--->base de datos

Si lo hago bien, mi control de servidor DevExpress debería poder delegar una solicitud de filtrado (por ejemplo, déjame los 10 primeros solamente) a través de todas estas capas hasta la base de datos que luego aplica sus índices, etc. para realizar esa consulta.

¿Es correcto?

Edit: Es una alegría ver cobrar vida este hilo :-) Es difícil decidir qué respuesta aceptar porque me parecen igualmente buenas ...

+0

¿Estás seguro de que no "solo" necesitas implementar IQueryable y hacer llamadas al servicio web al back-end? No estoy familiarizado con el componente ... –

+0

buena pregunta, he estado luchando con esto pero nunca se me ocurrió una solución elegante. En implementaciones anteriores, proporcioné un parámetro "filtro" personalizado para mis métodos de servicio (que al final se analiza en una cláusula WHERE), y luego en los servicios agregué algunos criterios adicionales para garantizar la restricción de acceso. Editar: en ese caso trabajé con Telerik Grid, que genera filtros como consultas OQL – Ozzy

+0

@Vincent: la implementación de IQueryable es probablemente una parte de la historia, pero la menor: permite el uso de LINQ en la capa de presentación, pero no resuelve (?) el problema de cómo hacer que el filtrado y la clasificación sean delegados al DBMS. – chiccodoro

Respuesta

1

La implementación del List QueryData(string sqlQuery) le abrirá hasta un número casi infinito de problemas de seguridad.

Si necesita filtrar en función del acceso de seguridad, la implementación de OData tampoco será trivial, debe configurar la autorización/autenticación adecuada en el servicio WCF para poder filtrar aún más la consulta OData en función del usuario autenticado datos.

La forma más fácil de implementar operaciones de datos del lado del servidor cuando se recuperan datos de un servicio WCF sería interceptar las operaciones de clasificación/filtro de la Grilla en el código subyacente y luego llamar a un método especializado en el servicio WCF basado en el usuario lo está haciendo

+0

Aún necesita implementar algún tipo de mecanismo de autenticación y autorización en el lado del servidor. El lado del servidor no debe engañarse falsificando las solicitudes de otras personas. –

2

Pregunta realmente interesante! No creo que haya una respuesta correcta o incorrecta, pero creo que se pueden establecer algunos principios arquitectónicos.

En primer lugar, la "Arquitectura orientada a servicios" es un estilo arquitectónico que requiere la exposición de servicios empresariales para el consumo de otras aplicaciones. Ejecutar una consulta de base de datos no es un servicio, en mi opinión al menos. De hecho, proporcionar un servicio web para ejecutar SQL arbitrario es probablemente un antipatrón - omitiría el modelo de seguridad que proporcionan la mayoría de los servidores de bases de datos, no tendría control sobre las consultas - es relativamente fácil escribir un "seleccionar" sintácticamente correcto consulta que paraliza su base de datos (las combinaciones cartesianas son mis favoritas), y la sobrecarga del protocolo del servicio web haría que este enfoque fuera varias veces más lento que solo consultar la base de datos a través de rutas de acceso normales: LINQ o lo que sea.

Entonces, supongamos que acepta ese punto de vista: ¿cuál es la solución al problema?

En primer lugar, si desea la productividad del uso de la grilla DevExpress, probablemente deba trabajar de la misma manera que DevExpress quiere que funcione; si eso implica consultar directamente la base de datos, es la mejor manera de hacerlo. Si desea pasar a una SOA, y la grilla DevExpress no es compatible con eso, es hora de encontrar un nuevo control de grilla, en lugar de adaptar toda su arquitectura empresarial a un componente relativamente menor.

En segundo lugar - estructuralmente, ¿dónde debe hacer su clasificación, filtrado, etc.? Este es un concepto sencillo en SQL, pero desagradable cuando tratas de traducirlo a una especificación de servicio web: terminas rápidamente con una firma de método incomprensible ("getAccountDataForUser (userID, bool sortByDate, bool sortByValue, bool filterZeros, bool filterTransfers)") Por otro lado, realizar el filtrado y la clasificación en el cliente es complicado y lento.

Mi recomendación sería mirar el Specification Pattern - esto le permite tener firmas de métodos limpios, pero especifique la ordenación y el orden deseados de forma consistente.

+0

Acepto su punto de vista. La especificación OData parece una respuesta a este problema. No permite consultas SQL arbitrarias, pero admite el filtrado y la clasificación. Incluso podría ser compatible con un componente como DevExpress (pero todavía me pregunto, nunca lo he probado). – chiccodoro

1

"Esto debe ser un problema muy común, y estoy seguro de que ha sido resuelto de manera relativamente adecuada, ¿o sí?"

Dado el número de gatos pelados que hay en el mundo de los desarrolladores, tendría que decir que no.

WCF Data Services ofrece la mejor solución que he encontrado hasta ahora, pero su autenticación y autorización pueden ser complicadas. Hay una publicación decente que cubre los problemas del lado del servidor al respecto al http://blogs.msdn.com/b/astoriateam/archive/2010/07/19/odata-and-authentication-part-4-server-side-hooks.aspx. Configurar esto no es fácil, pero funciona bien.