Fixes and improvements

Apr 4, 2009 at 10:22 AM
Hi,

I found this project and i start to write based on it a simple Odbc Linq provider.

  • At this time , i found one bug in DbQueryProvider.cs on  public virtual IEnumerable<T> Execute<T>(QueryCommand command, Func<DbDataReader, T> fnProjector, object[] paramValues)

    For example i have this code sequence

var headers = from i in o.DocHeaders
where i.DocType == (int)SageClassLibrary.DataModel.EnumDocType.SalesOrder || i.DocType == (int)SageClassLibrary.DataModel.EnumDocType.PurchaseOrder
select i;

 v

ar lines = from i in o.DocLines
where i.DocType == (int)SageClassLibrary.DataModel.EnumDocType.SalesOrder || i.DocType == (int)SageClassLibrary.DataModel.EnumDocType.PurchaseOrder
select i;

 

 

v

ar gamma = headers.ToList();
var gamma2 = lines.ToList();


The evaluation of gamma works fine and the evaluation of gamma2 can throw an exception (in fact  it depending of garbage collector process)  that said that current datareader is still Open.

I made this fix to avoid this exception

DbQueryProvider.cs

        /// <summary>
        /// Execute an actual query specified in the target language using the sADO connection
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="paramValues"></param>
        /// <returns></returns>
        public virtual IEnumerable<T> Execute<T>(QueryCommand command, Func<DbDataReader, T> fnProjector, object[] paramValues)
        {
            this.LogCommand(command, paramValues);
            IEnumerable<T> result;
            DbCommand cmd = this.GetCommand(command, paramValues);
            DbDataReader reader = cmd.ExecuteReader();
            try
            {
                result = Project(reader, fnProjector);
            }
            finally{
                reader.Close();
            }
            return result;
        }

  • When i implemented my custom odbc provider i found a problem of order evaluation of update sentence

In TQSql the parameter are named for example

UPDATE Customers
SET Name=@p2
WHERE CustomerNo=@p1

In this example , IQToolkit eval the param list as

PARAM[0] ={ Param.Name=@p1}
PARAM[1] ={ Param.Name=@p2}

-> IT WORKS

In Std Odbc fashion

UPDATE Customers
SET Name=?
WHERE CustomerNo=?

In this example , IQToolkit eval the param list as

PARAM[0] ={ Param Value of CustomerNo }
PARAM[1] ={ Param Value of Name }

-> IT DOESN'T WORK

because the outcoming query become

UPDATE Customers
SET Name={Value of CustomerNo Param}
WHERE CustomerNo={Value of Name}

That's why i made this improvement in DbExpressionVisitor.cs On 

        protected virtual Expression VisitUpdate(UpdateExpression update)
        {
            var table = (TableExpression)this.Visit(update.Table);
            var assignments = this.VisitColumnAssignments(update.Assignments);
            var where = this.Visit(update.Where);
            var result = this.Visit(update.Result);
            return this.UpdateUpdate(update, table, where, assignments, result);
        }

I'm very happy to find this project and i'm also impressed of the quality of this work !
Nice et great job !
I have many many many questions....
Regards
Cyril

Apr 6, 2009 at 8:45 AM

Sorry, the update of  public virtual IEnumerable<T> Execute<T>(QueryCommand command, Func<DbDataReader, T> fnProjector, object[] paramValues) doesn't work (i made a mistake by taking a old source test of my project).

To close datareader after dataset reading, you can override Project function on you inherited  DbQueryProvider and add at the end simply datareader.Close();

That works

Regards

Cyril

Apr 7, 2009 at 5:09 PM
Hi Cyril,

I am seeing the exception you mention where the command still has an open DBReader attached.  I tried the patch you mention (closing the reader explicitly in the Project() function), but it does not seem to help.  If it is a GC problem (and it certainly acts like one), I'm not sure how to fix it.  I've also tried Disposing the command object in Execute<T>.  Have you made any progress on this?
Apr 7, 2009 at 5:16 PM
Oops -  it's not a GC problem.  The code relies on having MARS enabled on the connection string.   I switched that on and the problem disappeared.  I was getting fooled because the error would rarely pop-up in the debugger, but would always occur when running free (or while profiling).
Apr 7, 2009 at 7:22 PM

Hi,

I don’t know exactly what happens but I did this and it works everytime (I think it was due to yield internal management  may be)!

    public class  CustomDbQueryProvider : DbQueryProvider

{

public CustomDbQueryProvider(DbConnection connection, QueryPolicy policy, TextWriter log):base

            (connection,policy,log)

        {

        }

public override IEnumerable<T> Project<T>(DbDataReader reader, Func<DbDataReader, T> fnProjector)

        {

            try

            {

                while (reader.Read())

                {

                    T value = fnProjector(reader);

                    IClassConverter iclassconverter = value as IClassConverter;

                    if (iclassconverter != null)

                        value = (T)iclassconverter.ConvertClass();

                    IDbOwner idbowner = value as IDbOwner;

                    if (idbowner != null) idbowner.Attach(this);

                    yield return value;

                }

            }

            finally

            {

                reader.Close();

            }

        }

}

I have question how can pass the object type  before it created  (object type is depending on data row) ?(I did this it ‘s not sound so good for me).

Regards

Your lib is great but very complex !

De : erikj999 [mailto:notifications@codeplex.com]
Envoyé : mardi 7 avril 2009 19:17
À : cyril@egnx.com
Objet : Re: Fixes and improvements [IQToolkit:52263]

From: erikj999

Oops - it's not a GC problem. The code relies on having MARS enabled on the connection string. I switched that on and the problem disappeared. I was getting fooled because the error would rarely pop-up in the debugger, but would always occur when running free (or while profiling).

Read the full discussion online.

To add a post to this discussion, reply to this email (IQToolkit@discussions.codeplex.com)

To start a new discussion for this project, email IQToolkit@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

No virus found in this incoming message.
Checked by AVG - www.avg.com
Version: 8.0.238 / Virus Database: 270.11.44/2044 - Release Date: 04/06/09 18:59:00