views:

131

answers:

1

Please look at my sourcecode.

public class EntityQuery
{
    public static Func<AdventureWork2008Container, IQueryable<SalesPerson>> selectQuery = CompiledQuery.Compile
    (
        (AdventureWork2008Container aw) =>
        (
            from s in aw.SalesPerson
            join e in aw.Employee on s.BusinessEntityID equals e.BusinessEntityID
            join p in aw.Person on s.BusinessEntityID equals p.BusinessEntityID
            join bea in aw.BusinessEntityAddress on s.BusinessEntityID equals bea.BusinessEntityID
            join a in aw.Address on bea.AddressID equals a.AddressID
            join sp in aw.StateProvince on a.StateProvince equals sp
            select s
        )
    );

    public decimal Select(AdventureWork2008Container aw)
    {
        SalesPerson result = selectQuery(aw).First();
        return result.SalesYTD;
    }

    public decimal Select2(AdventureWork2008Container aw)
    {            
        SalesPerson result =
        (
            from s in aw.SalesPerson
            join e in aw.Employee on s.BusinessEntityID equals e.BusinessEntityID
            join p in aw.Person on s.BusinessEntityID equals p.BusinessEntityID
            join bea in aw.BusinessEntityAddress on s.BusinessEntityID equals bea.BusinessEntityID
            join a in aw.Address on bea.AddressID equals a.AddressID
            join sp in aw.StateProvince on a.StateProvince equals sp
            select s
        ).First();

        return result.SalesYTD;
    }
}

I try to call Select method about 1000 times and call Select2 method about 1000 times. But the result shows me that Select2 method is a bit faster than Select method about 0.005 s.(0.052/0.057 s.) Moreover, this capture doesn't include time for creating EntityQuery object.

What's wrong with my source code?

PS. the following code show how to call methods.

    private void button1_Click(object sender, EventArgs e)
    {
        using (AdventureWork2008Container aw = new AdventureWork2008Container())
        {
            EntityQuery eq = new EntityQuery();

            eq.Select(aw);
            long lastTime = DateTime.Now.Ticks;

            for (int i = 0; i < 1000; i++)
            {
                eq.Select(aw);
            }
            listBox1.Items.Add("Select 1 : " + ShowTime(lastTime));
        }

        GC.Collect();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        using (AdventureWork2008Container aw = new AdventureWork2008Container())
        {
            EntityQuery eq = new EntityQuery();

            eq.Select2(aw);
            long lastTime = DateTime.Now.Ticks;

            for (int i = 0; i < 1000; i++)
            {
                eq.Select2(aw);
            }
            listBox1.Items.Add("Select 2 : " + ShowTime(lastTime));
        }

        GC.Collect();
    }
A: 

In Select2() generated code is

SELECT TOP 1 * FROM ...

In Select() aggregating is done on top of request. Don't know for sure, but it could lead to .Compile() results being discarded.

Try to move .First() into the compiled query.

public static Func<AdventureWork2008Container, SalesPerson> selectQuery = CompiledQuery.Compile
(
    (AdventureWork2008Container aw) =>
    (
        from s in aw.SalesPerson
        join e in aw.Employee on s.BusinessEntityID equals e.BusinessEntityID
        join p in aw.Person on s.BusinessEntityID equals p.BusinessEntityID
        join bea in aw.BusinessEntityAddress on s.BusinessEntityID equals bea.BusinessEntityID
        join a in aw.Address on bea.AddressID equals a.AddressID
        join sp in aw.StateProvince on a.StateProvince equals sp
        select s
    ).First();
);

Hope this will help.

elder_george
Thanks. I try it. It works! In select top 1 case, cached query is faster than non-cached query about 17 times. Moreover, in select all case; cached query is faster than non-cached query about 3 times (I think most of time is spent for fetching data).
Soul_Master