Date Image Saturday, October 23, 2010 | Kategoriler | Sql, Ado.Net, Asp.Net, C#, MVC, Tümü

Asp.Net MVC 2 Veri Sayfalama - 1 : Sql

Yazılım uygulamalarının en çok tekrar eden bölümlerindendir veri sayfalama. Bazen vakit kaybı bazen de önemli bir çalışma olarak adlandırılabiliyor. Bu yazımda, başlamak istediğim veri sayfalama serisinin ilk ayağı olan sql server tarafında sayfalamadan bahsedeceğim. Sql server tarafında derken, sayfalama işlemlerinde, tek bir sayfada gösterilmesi gereken dataların sql server üzerinde karar verilmesi ve geriye sadece istenen sayfaların dönmesini istiyoruz.
Bu işlemler için tabiki ado.net kullanacağız. Benim de bir süredir uzak kaldığım bir yazı ado.net yapısı :) bunda gelişen ORM yapılarının büyük etkisi bulunmaktadır. Bir çok işlemi otomatikleştirerek yazılım geliştiricilere zaman kazandıran ve esnek yapılarıyla orm tool lar zaman içinde bir çok kişinin tercihi olmuştu.
Sayfalama işlemlerini Asp.Net MVC 2 üzerinde göstermek istiyorum. Aslında bu yazıyı yazmaya başladığımda MVC 3 release olmamıştı bu nedenle MVC 2 ile uygulamayı yazmayı düşünmüştüm, zaten MVC 2 de kullanılabilir en iyi versiyonudur diye düşünüyorum.
Uygulamamız için gereken ilk şey bir MVC 2 projesi açmak. Bunu yhaptıktan sonra Models altına uygulamamızda kullanacağım Product sınıfını ekliyorum. Northwind database ini kullanacağım ve Product tablosunu nesnel olarak temsil edecek olan class ımız Product class ı olacak. Ancak bu class içerisinde Product tablosunun tüm alanları yer almayacak, istenirse eklenebilir ancak ben sadece 4 alan seçmeyi tercih ediyorum.

Product.cs :

public class Product
    {
        public int Id { getset; }
        public string Name { getset; }
        public decimal UnitPrice { getset; }
        public byte UnitsInStock { getset; }
    }

 

 

Daha sonra Controllers altna bir Controller ekliyoruz. Bu controller hazırlayacağımız modelimizi işleyerek bir sonuç oluşturduktan sonra bunu hazırlayacağımız view imize gönderecek. Yani modeli controllerda işleyerek view ile kullanıcıya göstereceğiz. Bu anlattıklarım MVC yapısından başka bir şey değil.
SqlPagingController adında bir controller ekleyelim. Controller içerisinde de bir ActionResult döndüren bir metota ihtiyacımız olacak.

SqlPagingController.cs :

public ActionResult Page(int index = 1)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            SqlConnection con = new SqlConnection
            
(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"]
                                 .ConnectionString);
 
            string query = "SELECT  ProductID, ProductName,UnitPrice,UnitsInStock,
                            (Select Count(ProductID) From Products) 
                            FROM (SELECT ROW_NUMBER() 
                            OVER (ORDER BY ProductID ASC) AS Row, 
                            ProductID, ProductName,UnitPrice,
                            UnitsInStock FROM Products) AS PagedProducts 
                            WHERE Row Between  
                            (@index - 1) * @limit + 1 and @index*@limit"
;
 
            SqlCommand com = new SqlCommand(query, con);
            com.Parameters.AddWithValue("@index", index);
            com.Parameters.AddWithValue("@limit", 10);
            SqlDataAdapter dap = new SqlDataAdapter();
            dap.SelectCommand = com;
            DataTable dt = new DataTable();            
            con.Open();
            dap.Fill(dt);
            con.Close();
            List<Product> products = new List<Product>();
 
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                products.Add(new Product
                                        {
                                            Id = Convert.ToInt32(dt.Rows[i][0]),
                                            Name = dt.Rows[i][1].ToString(),
                                            UnitPrice = Convert.ToDecimal(dt.Rows[i][2]),
                                            UnitsInStock = Convert.ToByte(dt.Rows[i][3])
                                        }
                            );
            }
 
            ViewData["productCount"] = Math.Ceiling(((int)(dt.Rows[0][4]) / 10.0));
 
            sw.Stop();
            ViewData["sw"] = sw.ElapsedMilliseconds;
 
            return View(products);
        }

Buradaki ActionResult dönüş tipindeki Page metotumuz index adında bir parametre almaktadır. Bu kısımları belki bir mvc makalesinde daha açık bir şekilde dile getirebilirim. Şuan için bir açıklama yapacak olursak, MVC ile geliştirilen projelerde uygulama sayfalarının adreslerinin route tablolarıda tutulduğunu görürüz. Uygulamaya gelen requestler route table a bakılarak ilgili adrese yönlendirilirler. Şimdi bu Controller için route table eklememiz gerek route a bir bakalım ve daha iyi anlayalım.

Global.asax :

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                "Default",
                "{controller}/{action}/{index}",
                new 
                    { 
                        controller = "SqlPaging"
                        action = "Page"
                        index = UrlParameter.Optional 
                    }
            );           
        }
 
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
 
            RegisterRoutes(RouteTable.Routes);
        }




 

Global.asax ta görüldüğü üzere RegisterRoutes metotunda istediğimiz url adreslerini route table a ekliyoruz. Öncelikle route umuza bir isim veriyoruz, burada Default olarak isimlendirdiğim. Sonra url formatı default olarak bu şekildedir ve controller karşılığında eklediğimiz SqlPaging Controller ı, action karşılığında ise action result geri dönüş tipindeki Page action ımız, url formatında görülen index ise Page action ımızın aldığı index parametresidir ve bu parametre opsiyonel olarak işaretlenerek girilmesinindeki zorunluluk kaldırılmıştır.Burada yapılan işlemler Apptication start olduğunda görüldüğü üzere route table a kaydedilerek gelen isteklerde kullanılmak üzere saklanır.
http://siteAdresi/SqlPaging/ ya da http://siteAdresi/SqlPaging/Page/2 şeklinde gelen istekler Default route ile Page action ına yönlenecek ve kullanıcıya bu action için tanımlanmış view ile gösterilecektir.

Model ve Controller kısımları tamamlandıktan sonra bilgileri kullanıcıya göstermeliyiz. Bunun için kolay bir yol olan actin a sağ tıklayarak Add View diyoruz ve master page vs. seçimi yaptıktan sonra Create a strongly-typed view seçeneğini işaretlereyerek alttaki dropdowndan Modelimzde bulunan Product sınıfını seçiyoruz. Bu seçim, oluşan view e bir model datası gönderilmesini ve bu datanın tipinin de Product olmasını sağlıyor. Son olarak da View Content i Empty yerine List seçiyoruz ve Model datasının bir IEnumarable interface li bir List ile oluşmasını ve default olarak template ile bir tablo oluşmasını sağlıyoruz.

Page.aspx :

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<IEnumerable<DataPagingSeries.Models.Product>>" %>
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Sql İle Sayfalama
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Sql İle Sayfalama</h2>
    <table>
        <tr>
            <th>
                Id
            </th>
            <th>
                Name
            </th>
            <th>
                UnitPrice
            </th>
            <th>
                UnitsInStock
            </th>
        </tr>
        <% foreach (var item in Model)
           { %>
        <tr>
            <td>
                <%: item.Id %>
            </td>
            <td>
                <%: item.Name %>
            </td>
            <td>
                <%: String.Format("{0:F}", item.UnitPrice) %>
            </td>
            <td>
                <%: item.UnitsInStock %>
            </td>
        </tr>
        <% } %>
        <tr>
            <th colspan="4">
                <%
                    int productCount = Convert.ToInt32(ViewData["productCount"]);
                                        
                    for (int i = 0; i < productCount; i++)
                    {%>
                <%: Html.RouteLink((i+1).ToString(), "Default"new { index = i + 1 })%>
                <%%>
            </th>
        </tr>
    </table>
    <div style="background-color:Yellow;"><%: "Süre :" + ViewData["sw"] + "ms" %></div>
</asp:Content>

Artık sayfamızı test etme zamanımız geldi demektir.

MVC 2 Sql Data Paging With Sql
Sayfamızı açtığımızda product ların listelendiği tablomuzu görmekteyiz, altta bulunan sayfa numaraları ile datalar arasında gezinebiliriz.

Etiketler : .Net , Asp.Net , Orm , MVC2 , Sql , Sql Server 2008 , MVC3 , Northwind