Sunteți pe pagina 1din 50

LINQ TO SQL

Linq es el nuevo ORM Object Relational Model que trata de saltar la brecha existente entre dos mundos otrora incompatibles: Los lenguajes de programacin y los lenguajes de acceso a bases de datos. Antes de Linq, los lenguajes de programacin no tenan nocin de los datos, y por ello nos encontrbamos escribiendo sentencias SQL en strings, sin oportunidad que los lenguajes nos pudieran ayudar con intellisense (que automticamente liste tablas, campos, etc.) y con revisin de sintaxis, etc.

CREANDO EL MODELO
Asumimos que tenemos ya un proyecto. En nuestro ejemplo, es un proyecto Web (conocidos en el mundo .NET como ASP.NET). En el Solution Explorer dar click derecho sobre el nombre del proyecto y pida la opcin Add New Item

Escoger el tem: LINQ to SQL Classes y en el nombre (Name) pngale un nombre descriptivo, como Northwind.dbml Presione en Add.

Aparece un mensaje indicando que insertar el archivo dentro de la carpeta App_Code. Conteste que S. Aparece el Object Relational Designer.

Note que a la derecha del Object Relational Designer hay una zona vertical para insertar mtodos. Si esta zona est escondida y desea verla, puede encenderla dando click derecho sobre el Object Relational Designer y pidiendo la opcin Show Methods Pane.

Ac puede crear entidades y relaciones manualmente, o los puede crear a partir de tablas de la base de datos, yendo al Server Explorer y arrastrando tablas al rea de diseo.

Note que el diseador trata de convertir los nombres de tabla en singular: Products se convierte en Product. Si desea cambiar el nombre, de doble click sobre el nombre. 3

Es posible tambin insertar objetos como Vistas. En este ejemplo, hemos adicionado la vista Invoices:

Si quiere agregar Procedimientos Almacenados (Stored Procedures), arrstrelo hacia el rea de mtodos. En este ejemplo, hemos arrastrado el procedimiento almacenado llamado Ten Most Expensive Products (Los 10 Productos Ms Caros) hacia el rea de mtodos.

Recuerde que el rea debe estar visible con ShowMethods Pane.

Note que hay una relacin entre Product y Category. Automticamente en el DataContext genera una propiedad Category dentro del objeto Product, de forma que podemos accesar a Product.Category.CategoryName. Esta relacin puede ser modificada al seleccionarla. Note que la Cardenality es OneToMany (Uno a muchos).

Uno de los ajustes que podemos hacer es que slo carguen imgenes cuando son necesarios, para ahorrar ancho de banda. Por ejemplo, el campo Picture de la tabla Category:

Si quisiera usar Stored Procedures para insertar, modificar o eliminar, ac mostramos dnde deben especificarse:

Para especificar un Stored Procedure, escoja la opcin Customize

Modificaremos nuestro DataContext para la siguiente demostracin:

Y en la pgina web Default.aspx dejaremos caer un GridView:

Le puse un nombre ms bonito al GridView: gvNorthwind 7

El cdigo queda as:

Partial Class _Default Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim db As New NorthwindDataContext ' product tiene la interface iEnumerable, ' que permite DataBinding Dim product = From p In db.Products _ Select p gvNorthwind.DataSource = product gvNorthwind.DataBind() End Sub End Class

Lo corremos (posiblemente aparezca un mensaje pidiendo cambiar el Web Config para poder debug. Contestemos que s):

Modificamos nuestra expresin LINQ para que slo muestre los productos cuya categora tenga un nombre especfico. Note que este tipo de query implica un JOIN entre dos tablas.
Dim product = From p In db.Products _ Where p.Category.CategoryName = "Beverages" _ Select p

Pondremos un breakpoint y vamos a correr de nuevo la aplicacin:

Una vez interrumpidos por el breakpoint, podemos ver los datos devueltos:

Supuestamente se tendra que ver tambin el Query, y aparece una lupa que hay que darle click. En el video, aparece la siguiente ventana:

El resultado de correr la aplicacin es la siguiente:

Modificaremos nuestra expresin LINQ para mostrar otras capacidades:


Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim db As New NorthwindDataContext ' product tiene la interface iEnumerable, ' que permite DataBinding Dim product = From p In db.Products _ Select p.ProductID, _ p.ProductName, _ numOrders = p.Order_Details.Count, _ revenue = Aggregate detail In p.Order_Details _ Into Sum(detail.UnitPrice * detail.Quantity) gvNorthwind.DataSource = product gvNorthwind.DataBind() End Sub

10

Note que estamos haciendo un .Count de los Order_Details de p. Y luego, hacemos un aggregate usando p.Order_Details sumando la multiplicacin del precio unitario con la cantidad, para tener el valor total de un producto.

Nota: No s por qu el orden de las columnas sale de esa manera. Tal vez haya que especificar directamente en el GridView las columnas que queremos ver. Vamos a Paginar en el Server, pues hay muchos resultados. En el siguiente ejemplo vamos a la fila 50 y tomamos 10 registros.
gvNorthwind.DataSource = product.Skip(50).Take(10) gvNorthwind.DataBind()

Vamos a mover el cdigo de acceso hacia una rutina aparte, para que lo podamos llamar desde varias partes. Parametrizamos la fila inicial con un parmetro llamado startRow

11

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim row As Integer = Convert.ToInt32(Request.QueryString("startRow")) bindProducts(row) End Sub Protected Sub bindProducts(ByVal startRow As Integer) Dim db As New NorthwindDataContext ' product tiene la interface iEnumerable, ' que permite DataBinding Dim product = From p In db.Products _ Select p.ProductID, _ p.ProductName, _ numOrders = p.Order_Details.Count, _ revenue = Aggregate detail In p.Order_Details _ Into Sum(detail.UnitPrice * detail.Quantity) gvNorthwind.DataSource = product.Skip(startRow).Take(10) gvNorthwind.DataBind() End Sub

El resultado, si ponemos un Query String as es: http://localhost/DevCare/WebSiteLinqTest20080204/Default.aspx?startRow=50

Parecera aca que primero se hace el Select trayendo todos los datos, y luego se pagina. Sin embargo, LINQ utiliza un modelo de Deferred Execution (Ejecucin Diferida), que le permite ser ms eficiente.

12

Modificaremos el Mapping File (para el Data Context) ligeramente para la siguiente demostracin:

Agregamos 3 botones al formulario ASP.NET. Les puse nombres bonitos como: btnLame, etc.

13

Queremos buscar productos caros que no se estn vendiendo bien (Productos Lame). El SQL para dicha operacin es el siguiente:
Select p.ProductID, p.ProductName, p.UnitPrice, p.ReorderLevel, sum(od.Quantity) as "UnitsSold" from Products as p, "Order Details" as od where od.ProductID = p.ProductID and p.UnitPrice > 15 group by p.ProductID, p.ProductName, p.UnitPrice, p.ReorderLevel having sum(od.Quantity) < 200 order by UnitSold

En nuestro cdigo ASP.NET para el botn btnLame escribimos el siguiente cdigo:


Protected Sub btnLame_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnLame.Click Dim db As New NorthwindDataContext Dim r = From p In db.Products _ Where p.UnitPrice > 15 And _ p.Order_Details.Sum(Function(x) x.Quantity) < 200 _ Select p gvNorthwind.DataSource = r gvNorthwind.DataBind() End Sub

Al correrlo y oprimir el botn Lame tenemos los productos caros que no tienen mucho movimiento:

14

Vamos actualizar los ReorderLevel a cero, pues NO queremos pedir ms de estos productos.
Protected Sub btnLame_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnLame.Click Dim db As New NorthwindDataContext Dim r = From p In db.Products _ Where p.UnitPrice > 15 And _ p.Order_Details.Sum(Function(x) x.Quantity) < 200 _ Select p For Each p As Product In r p.ReorderLevel = 0 Next db.SubmitChanges() gvNorthwind.DataSource = r gvNorthwind.DataBind() End Sub

Y vemos que todos los ReorderLevel estn en cero. Un punto interesante es que LINQ slo envi dos Update, pues el producto con ProductID=9 ya tena cero desde antes y no era necesario actualizarlo. Nota: Usa optimistic concurrency, por lo que el WHERE lleva todos los campos.

TRANSACCIONES
Antes de usar las transacciones, hay que agregar una referencia a System.Transactions. Botn derecho sobre el proyecto, y pedir la opcin de Property Pages. Colquese en References y oprima el botn Add Agregue System.Transactions

15

16

Y modificamos nuestro cdigo:


Protected Sub btnLame_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLame.Click Using ts As New Transactions.TransactionScope Dim db As New NorthwindDataContext Dim r = From p In db.Products _ Where p.UnitPrice > 15 And _ p.Order_Details.Sum(Function(x) x.Quantity) < 200 _ Select p db.Products.DeleteAllOnSubmit(r) db.SubmitChanges() gvNorthwind.DataSource = r gvNorthwind.DataBind() Transactions.Transaction.Current.Rollback() End Using End Sub

Ponemos un breakpoint en el Transactions.Transaction.Current.Rollback() y cuando lo corremos y se queda trabado en el breakpoint, si vamos al SQL, no podemos ver los registros, pues estn enllavados (locked). En la base de datos SQL podemos poner:
set transaction isolation level read uncommitted

que nos permite leer dirty records y al correr un query veremos que los registros parece que ya han sido borrados.

17

CREAR REGISTROS
Crearemos un nuevo Producto.
Protected Sub btnNewProduct_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnNewProduct.Click Dim db As New NorthwindDataContext Dim p As Product = New Product p.UnitPrice = -4.3 db.Products.InsertOnSubmit(p) db.SubmitChanges()

End Sub

Esto nos da un error, pues el ProductName no puede ser nulo. Lo interesante es que el error es detectado en el lado del cliente, y no por el servidor.

Este cdigo s funciona, pues pasa todos los Constraints:


Protected Sub btnNewProduct_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnNewProduct.Click Dim db As New NorthwindDataContext Dim p As Product = New Product p.ProductName = "Cosito" p.UnitPrice = 4.3 db.Products.InsertOnSubmit(p) db.SubmitChanges() End Sub

18

Este cdigo hace una insercin ms complicada:


Protected Sub btnNewOrder_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnNewOrder.Click Dim db As New NorthwindDataContext Dim chai As Product = _ db.Products.Single(Function(p) p.ProductName = "Chai") Dim tofu As Product = _ db.Products.Single(Function(p) p.ProductName = "Tofu") ' Nota: No tenemos que preocuparnos por AutoIncrement Dim o As New Order o.OrderDate = DateTime.Now o.RequiredDate = DateTime.Now.AddDays(2) o.Freight = 4.3 Dim li1 As New Order_Detail With {.Product = chai, .Quantity = 23} Dim li2 As New Order_Detail With {.Product = tofu, .Quantity = 33} o.Order_Details.Add(li1) o.Order_Details.Add(li2) Dim c As Customer = _ db.Customers.Single(Function(x) x.CompanyName.StartsWith("Alfred")) c.Orders.Add(o) db.SubmitChanges() End Sub

19

REGLAS DEL NEGOCIO


En el Solution Explorer, damos click derecho sobre el proyecto y pedimos Add New Item Pedimos un Class que le pondremos Order.cls

La clase resultante le ponemos el calificativo partial, pues extender a una clase existente.
Imports Microsoft.VisualBasic Partial Public Class Order Private Sub OnFreightChanging(ByVal value As Decimal?) If value <= 0 Then Throw New ApplicationException("No free shipping") End If End Sub Private Sub OnValidate(ByVal action As System.Data.Linq.ChangeAction) If RequiredDate < OrderDate Then Throw New ApplicationException("Time travel not possible") End If End Sub End Class

Modificamos nuestro cdigo que agrega la orden, para que rompa las reglas del negocio: :
Dim o As New Order o.OrderDate = DateTime.Now o.RequiredDate = DateTime.Now.AddDays(-2) o.Freight = -4.3

20

Si corremos la aplicacin y pedimos agregar la orden:

Si corregimos el Shipping, nos da el error de la fecha: Note que el lugar en donde da error vara con respecto al anterior.

21

LAS 4 FUNCIONES: SELECT, INSERT, UPDATE, DELETE


Agregamos cuatro botones para mostrar la funcionalidad:

El cdigo para el botn Select ser este:


Protected Sub btnSelect_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnSelect.Click showProducts() End Sub Protected Sub showProducts() Dim db As New NorthwindDataContext Dim products = From p In db.Products _ Where p.Category.CategoryName = "Beverages" _ Order By p.ProductID Descending _ Select New _ With {p.ProductID, _ p.ProductName, _ p.Category.CategoryName, _ p.UnitPrice} gvNorthwind.DataSource = products gvNorthwind.DataBind() End Sub

Y el resultado es ste:

22

Ahora insertaremos un registro:


Protected Sub btnInsert_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnInsert.Click Dim db As New NorthwindDataContext Dim p As New Product _ With { _ .ProductName = "Scott's Apple Juice", _ .UnitPrice = 2.4, _ .CategoryID = 1} db.Products.InsertOnSubmit(p) db.SubmitChanges() showProducts() End Sub

Al correrlo, y oprimir Insert tenemos: (en la pgina resultante, vemos el nuevo registro al inicio: Scotts Apple Juice)

23

Actualizando un registro:
Protected Sub btnUpdate_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnUpdate.Click Dim db As New NorthwindDataContext Dim p1 = (From p In db.Products _ Where p.ProductName.StartsWith("Scott's") _ Select p).Single p1.UnitPrice = p1.UnitPrice * 1.5 db.SubmitChanges() showProducts() End Sub

El resultado es que Scotts Apple Juice ya no cuesta 2.40 sino 3.60-

24

Ahora vamos a eliminar:


Protected Sub btnDelete_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnDelete.Click Dim db As New NorthwindDataContext Dim p1 = db.Products.First( _ Function(x) x.ProductName.StartsWith("Scott's")) db.Products.DeleteOnSubmit(p1) db.SubmitChanges() showProducts() End Sub

25

Al correrlo y oprimir Delete tenemos:

Ya no est el Scotts Apple Juice.

26

LINQDATASOURCE
Esta vez tendremos el acceso de datos en una clase aparte. Cree un proyecto tipo ClassLibrary que le puse: clsLibData20080211. Con File New Project

No usaremos el archivo que nos da por default: Class1.vb (podramos incluso borrarlo). Mas bien, vamos a agregar una clase Linq to SQL Data Context. En el Solution Explorer, damos click derecho sobre el nombre del proyecto clsLibData20080211 y pedimos Add New Item

27

(Le puse: dcNorthwind.dbml)

Desde el Server Explorer arrastr las tablas Orders, Order Details, Products, Categories, Customers. Note que puede acercarse y alejarse del diagrama de tablas utilizando Ctrl + Scroll Wheel del ratn. Damos un build al proyecto y nos olvidaremos por el momento de l.

28

PROYECTO WEB
Ahora crearemos otro proyecto, tipo ASP.NET (Web) para interfaz del usuario. Vamos a File Add New Web Site

Referenciamos el proyecto anterior clsLibData20080211, que es la que accesa los datos. En el Solution Explorer damos click derecho sobre nuestro proyecto Web:

En la pgina que nos da al inicio: Default.aspx agregamos un GridView. Yo lo nombr como gvProducts.

29

30

Damos click en la flechita en la parte superior derecha del GridView para tener el men contextual del GridView. Pedimos la opcin: Choose Data Source - <New Data Source>

Yo le puse de nombre: ldsNorthwind y luego, oprimimos OK.

Si no aparece el dcNorthwindDataContext, probablemente nos falte la referencia a la clase clsLibData20080211, o nos falta hacer un Build de nuestro proyecto Web.

31

Escogemos la tabla Products para este ejemplo.

Para nuestro ejemplo, tambin oprimimos el botn Advanced en donde le diremos que nuestro Data Source permitir actualizaciones a los datos:

32

Al regresar al Asistente, damos Finish y ya tenemos el Linq Data Source adicionado a la pgina Web:

En el men contextual del GridView podemos ahora habilitar paginacin, ordenamiento y hasta edicin. Tenemos las opciones de edicin debido a que en el LinqDataSource especificamos en Advanced que permitiera agregar, editar o eliminar.

Vamos a eliminar algunas de las columnas que se muestran al usuario. Para ello, debemos marcar la columna y en el men contextual del GridView (no de la Columna), pedimos Remove Column.

33

Para nuestro ejercicio, eliminamos las columnas UnitPrice y UnitsInStock. Le dimos un AutoFormat para que se vea mejor:

Si lo corremos, tenemos la pgina Web que muestra los datos.

34

Vemos que podemos editar (oprimiendo el link Editar), paginar, ordenar:

Sin embargo, vemos que SupplierID y CategoryID son Foreign Key que no son nada amigables para el usuario. Eliminaremos estas dos columnas, pero esta vez desde el cdigo fuente HTML de la pgina. Los marcamos y borramos:

35

En vez de ello, pondremos 2 template columns:

<asp:TemplateField HeaderText="Category" SortExpression="Category.CategoryName"> <ItemTemplate> <%#Eval("Category.CategoryName")%> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Supplier" SortExpression="Supplier.CompanyName"> <ItemTemplate> <%#Eval("Supplier.CompanyName")%> </ItemTemplate> </asp:TemplateField>

El resultado es que ahora vemos los nombres de la Categora (Beverages, Condiments, Produce) y del Proveedor (Exotic Liquids, New Orleans Cajun Delights, Grandma Kellys Homestead). Sin embargo, no podemos editarlos:

Los Joins son manejados automticamente por Linq.

36

Ahora modificaremos los Template Columns para permitir la modificacin. Seleccionamos la columna que queremos modificar (comenzaremos con Category) NOTA: Creo que es indiferente qu columna marquemos, pues ms tarde nos pregunta por la columna. Damos botn derecho, Edit Template y escogemos la columna: Column[3] - Category

Nos interesa el EditItemTemplate, que muestra lo que ver el usuario cuando est editando. Arrastramos un DropDownList (un combo box). Yo le puse el nombre: ddlCategory.

Vamos a necesitar un nuevo DataSource para el Drop Down List. Pedimos el men contextual del Drop Down List, Choose Data Source. En la caja de dilogo, donde pide Select a Data Source: pedimos <New Data Source>.

37

Yo le puse de ID: ldsCategory. Pedimos el Context Object que reside en nuestro Class Library clsLibData20080211:

38

Escogemos la tabla Categories. Slo vamos a querer los campos: CategoryID y CategoryName:

Damos Finish y regresamos al Asistente de Choose a Data Source Escogemos cul campo se va a mostrar: CategoryName, y cul campo tiene los valores a devolver: CategoryID, por el Drop Down List ddlCategory:

39

Regresamos a la edicin del Template. Tenemos ahora que especificar los Data Bindings, de forma que lo mostrado en el Drop Down List ddlCategory sea aplicado a la tabla Products del GridView. En el men contextual de ddlCategory pedimos la opcin: Edit DataBindings.

Para salir del modo de edicin del Template, en el men contextual del Template hay una opcin End Template Editing

Haremos el mismo proceso con el Supplier.

40

Al correrlo y pedir Editar tenemos lo siguiente:

Hoy ya podemos cambiar la categora y el proveedor (supplier) escogiendo de drop down lists.

FILTRANDO POR CATEGORAS


Ahora vamos a filtrar el grid a partir de un drop down list de categoras. El grid slo mostrar los productos de la categora escogida en el drop down list. Agregaremos un drop down list inmediatamente debajo de donde comienza el formulario. Lo haremos dentro del cdigo HTML:
<form id="form1" runat="server"> <div> Escoja una Categora: <asp:DropDownList ID="ddlCategoryFilter" runat="server"> </asp:DropDownList> </div>

Al Drop Down List le puse el nombre: ddlCategoryFilter

41

Usaremos el mismo LinqDataSource de Category ldsCategory que agregamos para el drop down list cuando estamos editando el grid. Sin embargo, el scope del data source es slo para el template. Lo sacaremos de all y lo pondremos fuera, donde puede ser usado por cualquier control del formulario. NOTA: Yo no estoy muy seguro que sea conveniente re-utilizar Data Sources. A m me pasaba con Windows applications que si dos controles usaban el mismo Data Source, ambos controles estaban conectados entre s. Tal vez en el Web este problema no se da.

Borramos el asp:LinqDataSource del Template, y lo colocamos en otra parte, casi al final del formulario:

42

Ahora regresamos a nuestr Drop Down List ddlCategoryFilter. En modo de diseo, pedimos su men contextual Choose a Data Source

Nota: Es posible que tenga que oprimir Refresh Schema para que aparezcan los campos para desplegar y para escoger el valor.

Para que inmediatamente al cambiar de categora nos muestre la pgina actualizada, pediremos: Enable AutoPostBack (Otra opcin sera poner un botn que lleve a cabo la accin). Tambin tenemos que indicarle al Grid que slo muestre los productos de una categora especfica.

43

Marcamos el Grid, vamos a su men contextual y pedimos: Configure Data Source Damos Next para pasar a la pantalla siguiente, donde nos muestra la tabla y los campos a mostrar. Oprimimos el botn Where

Queremos que la columa CategoryID sea igual (==) al Control ddlCategoryFilter. No se le olvide oprimir en Add para adicionar la expresin.

44

Hoy ya muestra los productos segn la categora elegida.

45

STORED PROCEDURES (PROCEDIMIENTOS ALMACENADOS)


Para este ejemplo aadiremos un LINQ to SQL class, que yo llam dcCustOrderList.dbml.

Abrimos el area de diseo de dcCustOrderList.dbml. Note que a la derecha hay un rea para mtodos. Si no se muestra, puede encenderla con botn derecho sobre el area de diseo, Show Methods Pane. Arrastraremos tambin la tabla Products para usarlo en el ejercicio.

46

Vamos a trabajar con el Stored Procedures llamado CustOrderHist que tiene el siguiente cdigo:

ALTER PROCEDURE CustOrderHist @CustomerID nchar(5) AS SELECT ProductName, Total=SUM(Quantity) FROM Products P, [Order Details] OD, Orders O, Customers C WHERE C.CustomerID = @CustomerID AND C.CustomerID = O.CustomerID AND O.OrderID = OD.OrderID AND OD.ProductID = P.ProductID GROUP BY ProductName

Si lo abrimos y le damos click derecho Execute:

Nos da como resultado:


Running [dbo].[CustOrderHist] ( @CustomerID = ALFKI ). ProductName ---------------------------------------Aniseed Syrup Chai Chartreuse verte Escargots de Bourgogne Flotemysost Grandma's Boysenberry Spread Lakkalikri Original Frankfurter grne Soe Raclette Courdavault Rssle Sauerkraut Spegesild Tofu Vegie-spread No rows affected. (13 row(s) returned) @RETURN_VALUE = 0 Finished running [dbo].[CustOrderHist]. Total ----------6 23 21 40 20 16 15 2 15 17 2 33 20

47

Del Server Explorer arrastramos el Stored Procedure CustOrderHist hacia el Methods Pane:

Agregamos una pgina Web DefaultCustOrderList.aspx y colocamos un GridView que llamamos gvCustOrderList.

El cdigo subyacente de la pgina es:


Partial Class DefaultCustOrderList Inherits System.Web.UI.Page Protected Sub Page_Load( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Me.Load Dim db As New dcCustOrderListDataContext Dim q = db.CustOrderHist("ALFKI") Me.gvCustOrderList.DataSource = q Me.gvCustOrderList.DataBind() End Sub End Class

48

Hoy trabajaremos con un Stored Procedure que tiene un OUTPUT value:


ALTER PROCEDURE dbo.GetProductsByCategory ( @CategoryID int, @count int=0 OUTPUT ) AS select ProductID, ProductName, CategoryID, UnitPrice from Products where CategoryID = @CategoryID order by ProductName select @count = @@ROWCOUNT RETURN

Lo creamos y luego lo arrastramos al area de diseo de dcCustOrderList.dbml. Agregamos un label a la pgina Web. Yo le puse de ID: lblRowCount

49

Ajustamos el cdigo para cuando cargue la pgina:


Protected Sub Page_Load( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Me.Load Dim db As New dcCustOrderListDataContext Dim rowCount As Integer? Dim q = db.GetProductsByCategory(1, rowCount) Me.lblRowCount.Text = _ string.Format( _ "Registros Encontrados {0}", _ rowCount) Me.gvCustOrderList.DataSource = q Me.gvCustOrderList.DataBind() End Sub

50

S-ar putea să vă placă și