LINQ TO SQL Performance

linq

 

 

LINQ o Language integrated query es un lenguaje de consultas integrado al lenguaje que fue introducido en las nuevas versiones de Visual Studio 2008, LINQ nos permite una sintaxis estándar para consultar diferentes fuentes de datos, sea SQL, XML u objetos en memoria.

Antes del framework 3.5, los desarrolladores típicamente usábamos ADO para consultar alguna que otra base de datos relacional, es decir si queríamos conectarnos y consultar alguna tabla usábamos las librerías de ADO específicamente System.Data.SqlClient. Si queríamos traer datos de la manera más rápida posible, entonces usábamos DataReaders, pero la responsabilidad del mantenimiento de la Data estaba a cargo del Desarrollador, y si el performance no era una de nuestras prioridades entonces optábamos por usar Datasets.

Luego de una conversación con mi amigo Dany Paredes, discutíamos acerca del Performance de LINQ TO SQL, para mi entender desarrollar con LINQ TO SQL es bastante rápido el desarrollo y todo eso, pero que ¿tal el performance?, decidí hacer las pruebas por mí mismo.

Escribí una Aplicación de Consola, para probar que tal el performance de LINQ TO SQL, ADO Datasets y ADO Datareader. La aplicación contiene 3 métodos los cuales cada uno de ellos consultan la tabla Customer de la base de datos northwind que contiene 91 registros 10,000 veces. En el caso para popular el Datareader cree una clase llamada clCustomer.

 

using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Configuration;
using System.Linq;



namespace LinqToSqlTest
{
    public class Program
    {
        public static string myconnectionstring = @"Data Source=.;Initial Catalog=northwind;User Id=sa;Password=sa;";

        static void Main(string[] args)
        {
            DateTime start;
            DateTime endTime;

            start = DateTime.Now;
            GetDataFromDatasets();
            endTime = DateTime.Now;
            Tiempo(start, endTime, "Usando Datasets");

            start = DateTime.Now;
            GetDataFromLinqToSQL();
            endTime = DateTime.Now;
            Tiempo(start, endTime, "Usando LINQ TO SQL");


            start = DateTime.Now;
            GetDataFromDataReaders();
            endTime = DateTime.Now;
            Tiempo(start, endTime, "Usando DataReaders");

            System.Console.ReadLine();
        }

        /// <summary>
        /// Traer los datos desde LINQ TO SQL
        /// </summary>
        private static void GetDataFromLinqToSQL()
        {
            LinqToSqlTestDataContext con = new LinqToSqlTestDataContext();
            var query = con.Customers;

            for (int i = 0; i < 10000; i++)
            {
                query.ToList();
            }
        }

        /// <summary>
        /// Metodo para Traer los datos en un reader
        /// </summary>
        private static void GetDataFromDataReaders()
        {
            SqlConnection con = new SqlConnection(myconnectionstring);
            string query = "select [CustomerID], [CompanyName], [ContactName], [ContactTitle], " +
            "[Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax]  from [dbo].[Customers]";
            SqlCommand command = new SqlCommand(query, con);
            con.Open();
            clCustomer sp = new clCustomer();
            for (int i = 0; i < 10000; i++)
            {
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    sp.CustomerID = rdr["CustomerID"].ToString();
                    sp.CompanyName = rdr["CompanyName"].ToString();
                    sp.ContactName = rdr["ContactName"].ToString();
                    sp.ContactTitle = rdr["ContactTitle"].ToString();
                    sp.Address = rdr["Address"].ToString();
                    sp.City = rdr["City"].ToString();
                    sp.Region = rdr["Region"].ToString();
                    sp.PostalCode = rdr["PostalCode"].ToString();
                    sp.Country = rdr["Country"].ToString();
                    sp.Phone = rdr["Phone"].ToString();
                    sp.Fax = rdr["Fax"].ToString();

                }
                rdr.Close();
            }
        }

        /// <summary>
        /// Metodo para traer los resultados en un Dataset
        /// </summary>
        private static void GetDataFromDatasets()
        {
            SqlConnection con = new SqlConnection(myconnectionstring);
            string query = "select [CustomerID], [CompanyName], [ContactName], [ContactTitle], " +
            "[Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax]  from [dbo].[Customers]";
            SqlCommand command = new SqlCommand(query, con);
            SqlDataAdapter da = new SqlDataAdapter(command);
            DataSet ds = new DataSet();
            for (int i = 0; i < 10000; i++)
            {
                da.Fill(ds);
            }
        }

        private static void Tiempo(DateTime dt1, DateTime dt2, string message)
        {
            string time = ((dt2.Ticks - dt1.Ticks) / 10000000.0).ToString();
            System.Console.WriteLine(message + ": " + time + " Segundos");
        }
    }

    public class clCustomer
    {
        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }

    }
}

¿Cuáles fueron los resultados?

linqtosqlScreen

  • Datasets (29.313 segundos)
  • LINQ TO SQL (18.629 segundos)
  • DataReaders (18.037 segundos)

Así que tenemos que LINQ TO SQL es mas rápido que un Dataset y ligeramente más lento que un DataReader.

Si quieres puedes probarlo tu mismo copiando el código y creando un Linq To Sql Class llamado northwind.dbml. Solamente es necesario la tabla Customers.

Espero que les sea de utilidad.