domingo, noviembre 02, 2008

¡Cuidado con el Entity Framework!

Aquí hay dragones, y manías sacadas de Java, que es peor...Una advertencia rápida: he recibido unos cuantos correos de programadores que quieren empezar proyectos con el ADO.NET Entity Framework, un añadido tardío del SP1 de Visual Studio 2008. Esta semana iré respondiendo todo el correo atrasado que tengo, pero prefiero ir adelantando aquí mi opinión.
Y mi opinión es que el Entity Framework (EF, en lo sucesivo) está demasiado verde. La versión del SP1, es cierto, está muy adelantada con respecto a las versiones liberadas durante las betas... pero eso es ya un síntoma de la fase actual del proyecto. En concreto, ¿cuáles son mis pegas?
  1. La principal: fallos de estabilidad. Puede que sea un problema de mi sistema, pero me he encontrado con errores al realizar operaciones tan simples como añadir una nueva tabla a un modelo ya existente. Me he encontrado de repente con tres errores en el código generado (relacionados con las "asociaciones", es decir, las claves externas). Al eliminar la tabla nueva y la tabla con la que se relaciona, me he encontrado en la extraña situación de que ninguna de las dos tablas vuelve a aparecer en el esquema relacional de la base de datos (pero sí aparecen en el Server Explorer y en SQL Server Management Studio).
  2. Creo que, por razones "ideológicas", se han dejado funcionalidad importante fuera. En concreto, el atributo identity de SQL Server es como si no existiese. Para crear una "entidad" cuya clave es autoincremental, disponemos de un constructor sin parámetros... y de un método estático que obliga a pasar un valor explícito para la clave.
  3. En realidad, detalles entrañables como el anterior son puntos del diseño, no una omisión o un descuido: los javalíes exigen que sus ORMs generen el código mínimo, y esas "chorradas" de claves automáticas entran en la categoría Prescindible para esta gente. Bien, me parece estupendo... pero queda usted avisado de lo que encontrará.
  4. Tenga muy presente que el EF debe funcionar con SQL Server, Oracle y lo que se presente. Eso puede ser una ventaja para determinadas aplicaciones. Pero para quien vaya a trabajar directamente con SQL Server, es más un problema que otra cosa. Ya le he dicho que se ignoran las identidades. Resulta que también se ignoran las columnas rowversion, que son la clave para acelerar el trabajo con la concurrencia optimista en SQL Server.
  5. La documentación es un asco. Lo siento, "asco" es la palabra exacta. De momento, hay que irse a Internet, y el individuo que ha creado la ayuda es un sádico que ha repartido cada bit de información útil entre cincuenta páginas diferentes, con el único propósito de hacerle sufrir. No hay libros sobre este tema: hay anunciado uno de David Sceppa en Amazon... para el 2010. Espero que el mío esté muchísimo antes. Ah, sí, hay vídeos en inglés, pero tardas una hora de metraje en enterarte de lo que podrías leer en cinco minutos. Una de las razones por la que los vídeos siguen siendo solamente "material de apoyo" en mis cursos a distancia.
  6. No tengo aún experiencia de primera mano en cómo funciona un sistema en tres capas basado en este invento. Es cierto que hay ahora un nuevo tipo de "ADO.NET Data Services", basado en HTTP. No sé cuán rápido puede ser este sistema para aplicaciones que necesitan verdaderamente rapidez y escalabilidad. Y a juzgar por lo que he visto, y por las experiencias con las tres capas en LINQ for SQL, me temo lo peor. Pero repito: todavía no he llegado a tanto.
Resumiendo, no lo veo muy claro. No es una opinión definitiva, pues como es natural, todavía me falta soltura con la herramienta. Puede que dentro de tres meses me parezca una maravilla. Mi consejo, para que no me malinterprete, es: sea prudente. En los mapas antiguos, en las zonas inexploradas se colocaban advertencias como Hic sunt dracones. Algún animal extraño nada en las ignotas aguas del ADO.NET Entity Framework. Puede terminar resultando un dragón, una sirena o un inofensivo calamar gigante.

... y para que se haga una idea de cómo bajan las aguas, eche un vistazo a este documento:
Le advierto que las críticas vienen, en este caso, del lado oscuro de la Fuerza (es decir, de los javalíes).

Etiquetas: ,

31 Comments:

Blogger Félix said...

Bienvenido
Hay un libro de Krasis press que no sé si has visto

lunes, noviembre 03, 2008 10:12:00 a. m.  
Blogger Alfredo Novoa said...

LinQ to Entities es una chapuza de campeonato lleno de inconsistencias que reintroduce errores desterrados hace décadas como la navegación en las consultas y no permite la actualización de conjuntos de datos (excepto saltándote LinQ y ejecutando directamente SQL).

Pero también tiene sus cosas buenas y es un paso torpe pero en la dirección correcta (probablemente por casualidad) para eliminar el llamado "impedance mismatch".

Y son justo las cosas buenas las que critican los descerebrados javalíes. Como por ejemplo que promueve que el SGBD se encargue de lo que se conoce como las "reglas de negocio" (es decir que se use para lo que está hecho). Aun en contra de todas las tonterías que dicen las guías de arquitectura de Microsoft.

Aunque de esto a usarlo hay un buen trecho. Yo solo lo tendría claro en el caso de una aplicación de prácticamente solo lectura.

lunes, noviembre 03, 2008 11:22:00 a. m.  
Blogger Ian Marteens said...

Hay un libro de Krasis press que no sé si has visto

No, no lo había visto. Lo encontré a última hora, "gugleando". Luego lo corrijo en el post (y me pido uno).

Yo solo lo tendría claro en el caso de una aplicación de prácticamente solo lectura

That's the point.

Doy por hecho que el sistema mejorará con el tiempo. Lo malo es el esfuerzo extraordinario que obliga a realizar a los usuarios potenciales (sobre todo, el de "investigación") y los recursos que desvía (los avances en multitier, por ejemplo, últimamente asumen que vas a usar uno de estos inventos).

lunes, noviembre 03, 2008 11:39:00 a. m.  
Blogger PabloNetrix said...

... los descerebrados javalíes ...

Alfredo Novoa IS BACK!! xDD

Ian, del libro de ADO.NET EF es coautor tu buen amigo (hasta donde yo sé) Octavio Hernández. De hecho yo tengo el de LINQ y te menciona en los Agradecimientos. ;-)


Saludos a todos

lunes, noviembre 03, 2008 4:56:00 p. m.  
Blogger -Kylix- said...

Mmm, por cierto el anuncio de microsoft de que va a concentrarse mas a EF en lugar de Linq to SQL, cambiara en algo esto?? como que MS quiere decir.. "La recomendacion es, utiliza EF porque LinQ to SQL tal vez ya no progrese tanto"

citando..
"We’re making significant investments in the Entity Framework such that as of .NET 4.0 the Entity Framework will be our recommended data access solution for LINQ to relational scenarios. We are listening to customers regarding LINQ to SQL and will continue to evolve the product based on feedback we receive from the community as well."
tomado del blog del "ADO .Net Team"

lunes, noviembre 03, 2008 5:13:00 p. m.  
Blogger Ian Marteens said...

es coautor tu buen amigo (hasta donde yo sé) Octavio Hernández

Sí, lo sé. De hecho, vendo el libro en mi página. Sabía que estaba escribiendo éste, pero no imaginé que fuese tan adelantado.

va a concentrarse mas a EF

El LINQ to SQL fue una chapucilla para ir abriendo el apetito. Se supone que, si estás interesado en un ORM, una de las principales razones es poder abstraerte de la base de datos concreta (Oracle, SQL Server, o lo que le echen), mientras que LINQ4SQL es sólo para SQL Server.

lunes, noviembre 03, 2008 7:36:00 p. m.  
Blogger Alfredo Novoa said...

El LINQ to SQL fue una chapucilla para ir abriendo el apetito. Se supone que, si estás interesado en un ORM, una de las principales razones es poder abstraerte de la base de datos concreta (Oracle, SQL Server, o lo que le echen), mientras que LINQ4SQL es sólo para SQL Server.

Pero igual que han hecho funcionar a LINQ to Entities con varios SGBD podían hacer lo mismo con LINQ to SQL.

Por otra parte eso de que funcione con todo tampoco es tan fácil. Con lo poco que he mirado me ha parecido ver que se pueden hacer consultas que con SQL Server solo se pueden resolver con CTEs. Así que de momento creo que podemos olvidarnos de MySQL y otros SGBD menores.

lunes, noviembre 03, 2008 9:09:00 p. m.  
Blogger Alfredo Novoa said...

Ya, esto que acabo de comentar era sobre LINQ to SQL. Parece ser que con LINQ to Entities lo han "arreglado" bajando la calidad del código SQL generado. Parece que LINQ to Entities es un gran paso hacia atrás con respecto a LINQ to SQL. Ya me parecía que lo que había de bueno tenía que ser por casualidad (al meter SQL en el puchero algo de buen sabor le tenía que dar). Eso sí, sigue siendo lo menos desastroso dentro de los ORM (Object Relational Mess).

martes, noviembre 04, 2008 3:11:00 a. m.  
Blogger Daniel said...

que bueno verte de nuevo amigo Ian. Se festeja tu regreso desde estas lejanas tierras.

miércoles, noviembre 05, 2008 12:46:00 p. m.  
Blogger Ian Marteens said...

Gracias, Ninex. Y lo bueno es que regreso con ganas de dar guerra...

@Alfredo:

Parece ser que con LINQ to Entities lo han "arreglado" bajando la calidad del código SQL generado.

Ahora, a eso súmale que el código generado en L4SQL estaba "optimizado" para la carga diferida... cuando en un escenario en tres capas, el estar conectándose constantemente para traerse tonterías es el mayor pecado. Por contra, cuando querías leer una entidad y todo el árbol que de ella cuelga, el código era ineficiente (y escarabájicamente pelotero), pues lo que se hacía era "componer" la suma de las cargas diferidas. Todavía tengo que ver qué hace LINQ4Ent en ese caso.

Ese es el motivo principal de que no haya habido ya una "cara oculta 3": no me parece razonable sacar un libro con cuatro hints sobre el funcionamiento de un sistema nuevo similares a los que ya están en la documentación. No puedo apoyar el uso de un sistema hasta estar convencido de que es realmente bueno. Prefiero vender menos, pero ofrecer la garantía de que lo que recomiendo, está al menos bien estudiado.

miércoles, noviembre 05, 2008 1:46:00 p. m.  
Blogger Ian Marteens said...

Por cierto, ¿alguno de vosotros ha trabajado con sockets? ¿Sabéis si existe alguna restricción pragmática en el tamaño de los trozos que se pueden enviar por un socket? Es que he visto un sistema ridículamente limitado por la supuesta necesidad de trocear mensajes en fragmentos de menos de 1KB. No dudo que exista un límite práctico, pero me parece increíble que éste se deje en el kilobyte de marras. Protocolos como el de SQL Server trabajan con un tamaño de registro varias veces superior.

miércoles, noviembre 05, 2008 1:58:00 p. m.  
Blogger Alfredo Novoa said...

Ahora, a eso súmale que el código generado en L4SQL estaba "optimizado" para la carga diferida...

Ya, lo de la carga diferida es justo lo que hace que se pueda generar código SQL eficiente que solo se puede crear usando CTEs.

Por ejemplo cuando creabas una variable local esta no era asignada y solo cuando materializabas se creaba una sola consulta que podía llegar a ser muy compleja dándole al optimizador de SQL Server la oportunidad de optimizarla y haciendo todo el proceso de un solo golpe en lugar de un ping pong de pequeñas consultas entre cliente y servidor típico de los engendros del tipo de Hibernate.

Por ejemplo si la variable local tenía un millón de registos y luego la filtrabas más adelante a 100, pues LINQ solo te traía los 100 al final, cosa que estaba muy bien.

Quitándole esto la potencia de LINQ baja muy considerablemente.

cuando en un escenario en tres capas, el estar conectándose constantemente para traerse tonterías es el mayor pecado.

Para solucionar esto yo hago 2 cosas:

1 Estar todo el rato conectado :-) (parece que no, pero se nota un huevo la diferencia)

2 Instalar un SGBD ligerito en el cliente (que corra en el mismo proceso que la aplicación) para tener allí todas las tonterías y conectar con el servidor solo para las cosas serias y para actualizar las tonterías solo cuando hace falta.

miércoles, noviembre 05, 2008 2:13:00 p. m.  
Blogger Alfredo Novoa said...

¿Sabéis si existe alguna restricción pragmática en el tamaño de los trozos que se pueden enviar por un socket? Es que he visto un sistema ridículamente limitado por la supuesta necesidad de trocear mensajes en fragmentos de menos de 1KB.

Claro que sí, pero 1KB ni en los tiempos de Maricastaña. Donde va que recomendaban usar 4KB. Con las ADSL de ahora no se donde estará el óptimo, pero supongo que bastante por encima. Para estas cosas no suele quedar otra que experimentar, y también depende del tipo de aplicación, claro está.

miércoles, noviembre 05, 2008 2:18:00 p. m.  
Blogger Ian Marteens said...

Claro que sí, pero 1KB ni en los tiempos de Maricastaña.

Ya me parecía a mí...

Además, ni siquiera se trata de una conexión remota, sino en una red local.

jueves, noviembre 06, 2008 3:42:00 p. m.  
Blogger Alfredo Novoa said...


Además, ni siquiera se trata de una conexión remota, sino en una red local.


Ya, entonces es distinto. A lo mejor la cosa viene de que el tamaño máximo del paquete ethernet es de 1538 bytes, que quitando los bytes de control se quedan en unos 1500.

El tamaño óptimo del paquete TCP depende mucho de la latencia de la red, así que para una red local el óptimo será mucho más bajo que para Internet. Pero para mi que algo si que lo puedes subir (hasta 1500 por descontado).

Los de SQL Server recomiendan 20.000 bytes para redes de alta latencia como Intenet, que me parece bastante razonable.

Pero yo de todas formas siempre haría experimentos, que estas cosas son liosas :-)

jueves, noviembre 06, 2008 8:04:00 p. m.  
Blogger Alfredo Novoa said...

Perdón, son 1518, que se quedan luego en 1500

jueves, noviembre 06, 2008 8:09:00 p. m.  
Blogger Ian Marteens said...

Sí, pero no se trata de eso: a tanto no llegan, estoy convencido. Además, es el propio protocolo quien se encarga de trocear los mensajes. Y la "restricción" impuesta por esta gente consiste en trocear ellos el mensaje, al más alto nivel (complicando de narices el protocolo que se han currado). Además, todo eso con el agravante de que el protocolo está diseñado en modo texto. Para pasar el número 255 tienen que pasar tres bytes en vez de uno. Y, ¡sorpresa!, nada de Unicode. Es ASCII puro y duro, por lo que han empezado a tener problemas con los acentos y las eñes.

jueves, noviembre 06, 2008 11:59:00 p. m.  
Blogger Alfredo Novoa said...

¡Buf! Que mala pinta tiene eso :(

Se me ocurre que lo de la longitud del paquete casi va a ser lo de menos.

viernes, noviembre 07, 2008 12:21:00 a. m.  
Blogger Unknown said...

A mi me da la impresión que ese "protocolo" viene heredado de alguna aplicación milenaria de Ms-DOS, y que se ha ido manteniendo por los años.

sábado, noviembre 08, 2008 10:15:00 p. m.  
Blogger Ian Marteens said...

Juan Antonio: tu opinión te honra. Te cuesta pensar que alguien haya podido crear tal horror partiendo de cero. ¡Pero no conoces las espantosas abominaciones de las que es capaz la especie humana!

De MSDOS nada. Esta aplicación se perpetró en el 2002 o 2003 como mucho, directamente sobre .NET v1.1. No hay circunstancias atenuantes.

domingo, noviembre 09, 2008 8:33:00 p. m.  
Blogger Al González said...

¡Hola Ian!

Hace tiempo que no te saludaba. Encuentro interesante la entrada y todos los comentarios vertidos tras ella. A pesar de que aún no domino del todo el tema de multicapa.

Muy interesante todo lo que comenta Alfredo Novoa, también.

Me llamó la atención el nombrecito éste de "Entity Framework", porque llevo ya un par de años trabajando en un "pequeño" framework que te permite manejar las filas de un conjunto de datos como verdaderas instancias de objetos.

Puedo acceder a los datos de cualquier fila sin que ocurra navegación (incluso modificarlos) y referirme a valores foráneos de una manera directa, sin usar molestas búsquedas explícitas.

Con esto evito el código "excesivo" que suele necesitarse en Delphi para hacer operaciones que no deberían ameritar más de una o dos sentencias.

// (obtener el nombre del supervisor de la zona del cliente de la factura)
NombreSupervisor := RecFactura ['IDCliente.IDZona.IDSupervisor.Nombre];

// (calcular el precio por el porcentaje del IVA que tiene asignado nuestro registro "Self")
Values ['PrecioTotal'] := Multiply ('Precio', 'IDIVA.Porcentaje');

// (verificar si el valor de un campo cambió respecto a su "OldValue")
If Rec ['Nombre'] <> Rec ['?Nombre'] Then
ShowMessage ('Cambió el nombre');

La palabra "Entity" aparece con frecuencia en el código de mi framework, porque todo está pensado alrededor del concepto de "entidad". Para que pueda emplearse POO a plenitud en la antigua calle donde viven los "data sets" de Delphi.

Digamos que encontré una manera de que la naturaleza de los conjuntos de datos convergieran con los propósitos de la POO. Y me siento feliz programando en esta cosa que hace las cosas más "obj-etivas".

Perdón si fue mucho rollo, sé que Delphi ya no es tu lenguaje predilecto. Sólo quería que supieras que le voy encontrando solución a algunos de sus más antiguos problemas de diseño (en lo que Embarcadero ordena el desarrollo de una nueva y renovada VCL). :)

Un abrazo.

Al González.

domingo, noviembre 09, 2008 9:57:00 p. m.  
Blogger Ian Marteens said...

Hola, Al. Welcome back.

porque llevo ya un par de años trabajando en un "pequeño" framework

Ese es uno de los problemas por los que detesto los ORMs: todo el mundo termina montándose el suyo. Es natural, y lo comprendo: causa más satisfacción reinventar la rueda y crear un ORM propio que utilizar alguno de los muchísimos ya existentes.

referirme a valores foráneos de una manera directa

Hum, lo mismo digo una tontería, ¿pero no te permiten hacer exactamente lo mismo los "typed datasets"? Asumo que Delphi soporta "typed datasets", ¿no?

Perdón si fue mucho rollo

No te preocupes: para eso existe esta página.

sé que Delphi ya no es tu lenguaje predilecto

No se trata de eso. El Delphi 2012 (si es que llega a esa fecha) será mi lenguaje favorito para el año 2005. Es un problema típico de la teoría de la relatividad.

martes, noviembre 11, 2008 10:44:00 a. m.  
Blogger Ian Marteens said...

También es verdad que debe existir un universo paralelo a éste en el que Delphi es mi lenguaje favorito. En ese otro universo, a Anders Hejlsberg le da una apoplejía cuando se va de Borland a Microsoft. Aunque también es cierto que en ese otro universo estoy casado con una multimillonaria y dedico mis innumerables ratos de ocio a la caza de conejos de playa.

martes, noviembre 11, 2008 10:47:00 a. m.  
Blogger Al González said...

...¿pero no te permiten hacer exactamente lo mismo los "typed datasets"? Asumo que Delphi soporta "typed datasets", ¿no?
Sospecho que tal asunción no lleva mucho de esperanza, Ian. ;)

No he oído hablar de ese concepto en Delphi, y hasta donde sé no existe algo nativo tan fácil como lo que he implementado para acceder así nada más, sin dramas, a campos de tablas relacionadas (quizá con ECO, pero no sé gran cosa de esa velada tecnología).

El framework se encarga de todo el trabajo sucio (por fin puedo hacer una simple multiplicación de dos campos sin irme a hacer "locates" o "queries" engorrosos y esas cosas).

Utilizo objetos derivados de TClientDataSet que pueden ir aumentando su número de filas conforme se realizan búsquedas, y tienen una nueva propiedad que llamé "RecClass", para indicarle cuál es la clase de objeto (entidad) cuya forma y comportamiento cada uno de los registros adoptarán. Además de procedimientos almacenados "virtuales" a nivel de la base de datos. Les he llamado así porque son SPs que curiosamente nunca son llamados por ninguna capa de la aplicación, y esa es una de las partes que más me divierte mencionar porque la gente se pregunta "¿entonces para qué los defines si no los llamas?". Siempre les digo que el hecho de que el programa no los llame no quiere decir que no los use. :)

Lo que sí es relativamente reciente en Delphi son los tipos genéricos (algo que entiendo ya lleva algo más de tiempo en otros lenguajes).

En una encuesta realizada en 2008 por CodeGear (ahora Embarcadero) se plantea muy sutilmente la posibilidad de que el TDataSet sea por fin reformado dentro de pocos años. El impacto será tremendo en la enorme industria de proyectos y componentes Delphi, pero definitivamente necesaria dicha reforma.

Espero poder lograr algo de influencia en ello. Disto mucho de ser uno de esos ingenieros de gran renombre que viajan de sur a norte por la costa oeste estadounidense, pero creo que no carezco de ideas interesantes para el mejoramiento de Delphi.

Un abrazo de poniente a oriente.

Al González. :)

sábado, diciembre 27, 2008 11:39:00 p. m.  
Blogger REDMAN- said...

Veo que todos intentais pensar una dinámica con vuestras diferencias para acceder a datos, pero ¿a alguien le preocupa la seguridad? ¿dais acceso a nivel de tablas en el gestor de bases de datos? ¿o dais acceso a todo?, no os dais cuenta que en el futuro la SEGURIDAD será un problema, todo debiera pasar por SCRIPTS (lo más parecido son procedimientos almacenados), a los que se debiera dar acceso personalizado. Pienso que el LINQ como el ENTITY FRAMEWORK como cualquier cosa que se le parezca nace muerta!

http://redmanlog.blogspot.com/2006/05/presentacin.html

lunes, diciembre 29, 2008 6:46:00 p. m.  
Blogger Alfredo Novoa said...

Redman, aquí no hablamos de seguridad por que eso ya queda cubierto por el SGBD y el cortafuegos, y es independiente de LINQ y del Entity Framework y similares.

Con un SGBD le puedes dar acceso personalizado a cada usuario o grupo de usuarios.

lunes, diciembre 29, 2008 8:26:00 p. m.  
Blogger REDMAN- said...

Pero si distribuyes una aplicación a un cliente los permisos en la base de datos ¿quien los da?

martes, diciembre 30, 2008 7:06:00 p. m.  
Blogger REDMAN- said...

A ver Alfredo, para que nos entendamos, ¿como configuras tu la seguridad en la base de datos?
(sistemas que yo sepa)

1.- Conectar con un usuario con todos los permisos
2.- Dar permisos a usuarios/grupos a nivel tablas/campos
3.- Crear roles de aplicación.
4.- Dar permisos a nivel de procedimientos almacenados

martes, diciembre 30, 2008 7:15:00 p. m.  
Blogger REDMAN- said...

Mi opinión es que si en el futuro queremos depender de las tecnologías la seguridad (ahora o dentro de 10 años) deberá acotar a cada USUARIO de un sistema a sus FUNCIONES exactas, o sea en un sistema de base de datos si quiero que sólo vea unos datos concretos cada vez que haga una sentencia dinámica debiera previamente otorgar permisos a tablas y campos concretos, si más adelante (en una actualización) se modifica una sentencia y se añade un CAMPO, habrá que preocuparse de que el usuario tenga acceso a ese CAMPO.
Pues bien si programo las sentencias como SCRIPTS (procedimientos almacenados), puedo hacer modificaciones sin que me afecte a la seguridad.

martes, diciembre 30, 2008 7:25:00 p. m.  
Blogger Alfredo Novoa said...

¿como configuras tu la seguridad en la base de datos?

Dar permisos a usuarios y grupos a nivel de tablas, vistas y procedimientos almacenados.

Aunque esto es un poco redundante por que las vistas son tablas y para un usuario no existen diferencias entre vistas y tablas.

deberá acotar a cada USUARIO de un sistema a sus FUNCIONES exactas, o sea en un sistema de base de datos si quiero que sólo vea unos datos concretos cada vez que haga una sentencia dinámica debiera previamente otorgar permisos a tablas y campos concretos

Pues eso.

si más adelante (en una actualización) se modifica una sentencia y se añade un CAMPO, habrá que preocuparse de que el usuario tenga acceso a ese CAMPO.
Pues bien si programo las sentencias como SCRIPTS (procedimientos almacenados), puedo hacer modificaciones sin que me afecte a la seguridad.


Creo que entiendo lo que quieres decir. Pero para eso se usan las vistas. Los procedimientos almacenados son sobre todo para encapsular sentencias de actualización complejas.

Además los SCRIPTS no tienen nada que ver con los procedimientos almacenados. Unas definiciones de tablas y vistas son tan script como unas definiciones de procedimientos almacenados

¡Feliz año!

miércoles, diciembre 31, 2008 5:44:00 p. m.  
Blogger REDMAN- said...

Feliz Año !
Un procedimiento almacenado puede hacer el mismo papel que una VISTA además puede hacer AUN más cosas, pero al no estar pensado para eso es más dificil de darle dicho uso.

viernes, enero 02, 2009 12:46:00 p. m.  

Publicar un comentario

<< Home