Mahdi Radi
Mahdi Radi

Reputation: 439

how use lambda expression on entity framework with high performance

I work on c# winforms. I use entity framework 6.

In my solution I have 2 project with A.BLL & A.DAL Names. (A.DAL added on A.BLL References)

A.DAL Project I have under method:

public decimal Sum(Func<ml_doc, bool> predicate, Func<ml_doc, decimal> sumColumn)
{
    try
    {
        using (dbEnteties = new Entities(Connection.CustomEntityConnection))
        {
            dbEnteties.ContextOptions.LazyLoadingEnabled = true;
            var dbe = dbEnteties.ml_doc;
            return dbe.Where(predicate).Sum(sumColumn);
        }
    }
    catch (Exception exp)
    {
        throw exp;
    }
}

A.BLL project I have under method (that use Sum method on A.DAL project) :

public decimal GetSum(long AccId, int? CntId, short BranchId, int BeginNumber)
{
    try
    {
        using (dal = new DAL.DocDA())
        {
            // Sum method referenced from A.DAL project
            return dal.Sum(
                x =>
                x.acc_id == AccId &&
                x.cnt_id.Equals(CntId) &&
                x.ml_doc_hdr.branch_id == BranchId &&
                x.ml_doc_hdr.number >= BeginNumber
                ,
                y => y.price);
        }
    }
    catch (Exception exp)
    {
        throw exp;
    }
}

When I use GetSum method (in A.BLL project) I get under exception:

There is already an open DataReader associated with this Command which must be closed first.

To solve this exception I add MultipleActiveResultSets=True to my connection string, this method works very slowy (for example 3 seconds).

I create under method on A.DAL project :

public decimal Sum2(long AccId, int? CntId, short BranchId, int BeginNumber)
{
    try
    {
        using (dbEnteties = new Entities(Connection.CustomEntityConnection))
        {
            dbEnteties.ContextOptions.LazyLoadingEnabled = true;
            var resultQuery = dbEnteties.ml_doc.Where(
                x =>
                x.acc_id == AccId &&
                x.cnt_id.Equals(CntId) &&
                x.ml_doc_hdr.branch_id == BranchId &&
                x.ml_doc_hdr.number >= BeginNumber
                );

            if (resultQuery.Count() != 0)
            {
                return resultQuery.Sum(x => x.price);
            }

            return 0;
        }
    }
    catch (Exception exp)
    {
        throw exp;
    }
}

When I use upper method (Sum2) this work fine and very fast (for example 0.003 second)

What is diffrence between Sum2 (on A.DAL project) & GetSum (on A.BLL projetc) Methods (It seems there are Same)?

How can change GetSum Method to work with high performance?

Upvotes: 2

Views: 833

Answers (1)

xanatos
xanatos

Reputation: 111850

This one:

public decimal Sum(Func<ml_doc, bool> predicate, Func<ml_doc, decimal> sumColumn)
{
    try
    {
        using (dbEnteties = new Entities(Connection.CustomEntityConnection))
        {
            dbEnteties.ContextOptions.LazyLoadingEnabled = true;
            var dbe = dbEnteties.ml_doc;
            return dbe.Where(predicate).Sum(sumColumn);
        }
    }
    catch (Exception exp)
    {
        throw exp;
    }
}

loads the full ml_doc table locally from the SQL server, and then executes the Where() and the Sum() operations locally.

This because your LINQ expression uses two Func<> delegates, so instead of using

it uses

Try changing it to:

public decimal Sum(Expression<Func<ml_doc, bool>> predicate, Expression<Func<ml_doc, decimal>> sumColumn)

The Sum2 method instead, by using directly some lambda functions, uses the Queryable.* methods, because the lambda functions are interpreted as Expression<>.

Upvotes: 5

Related Questions