DatePartExpression

Posts   
 
    
Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 23-Aug-2005 17:33:59   

Hello I'm trying to create my own expression type to allow the use of Daypart MSSQL function. I've taken example on the source code (Expression class) but I still have a (big?) problem.

Ok so here is my source code :

constructor :

public DatePartExpression(DatePartType type, ExOp operatorToUse, IEntityField2 rightOperand)
{
    InitClass();
    _rightOperand   = new ExpressionFieldElement(ExpressionElementType.Field, rightOperand, null);
    _operator       = operatorToUse;
    _type       = type;
}
public virtual string ToQueryText(ref int uniqueMarker, bool inHavingClause)
        {
            if(_creator==null)
            {
                throw new System.ApplicationException("DatabaseSpecificCreator object not set. Cannot create query part.");
            }

            StringBuilder queryText = new StringBuilder(128);
            _parameters.Clear();


            if (this.RightOperand != null) 
            {
                string leftOp   = this.ToDatePartText(this._type);
                [b]string rightOp   = this.OperandToText(ref queryText, this._rightOperand, ref uniqueMarker, false, inHavingClause);[/b]               
                queryText.AppendFormat(null, "DATEPART({0}, {1})", leftOp, rightOp);
            }

            return queryText.ToString();
        }

The original method a bit modified to return the text instead of append to the queryBuildler :

private string OperandToText(ref StringBuilder queryText, IExpressionElement operand, ref int uniqueMarker, bool isLeftOperand, bool inHavingClause)
        {
            IExpressionFieldElement fieldElement = null;

            switch(operand.Type)
            {
                case ExpressionElementType.Value:
                    IDataParameter parameter = _creator.CreateParameter("LO" + operand.GetHashCode().ToString(), ParameterDirection.Input, operand.Contents);
                    _parameters.Add(parameter);
                    uniqueMarker++;
                    parameter.Value = operand.Contents;
                    parameter.ParameterName += uniqueMarker.ToString();
                    return parameter.ParameterName;
                case ExpressionElementType.Field:
                    fieldElement = (ExpressionFieldElement)operand;
                    IEntityFieldCore fieldCore = (IEntityFieldCore)fieldElement.Contents;
                    if(fieldCore.ExpressionToApply!=null)
                    {
                        // add parameters to this expression's collection.
                        _parameters.AddRange(fieldCore.ExpressionToApply.Parameters);
                    }
                    [b][colorvalue="FF0000"]return string.Format("{0}", _creator.CreateFieldName(fieldCore, fieldElement.PersistenceInfo, fieldCore.Name, fieldCore.ObjectAlias, ref uniqueMarker, inHavingClause));[/color][/b]                case ExpressionElementType.Expression:
                    IExpression expressionToConvert = (IExpression)operand.Contents;
                    // pass on the name creator object
                    expressionToConvert.DatabaseSpecificCreator = _creator;
                    _parameters.AddRange(expressionToConvert.Parameters);
                    return string.Format("({0})", expressionToConvert.ToQueryText(ref uniqueMarker, inHavingClause));
            }
            throw new ArgumentException("Invalid ExpressionElementType:" + operand.Type.ToString());
        }

Ok now the problem is :

TestCase 'M:HRAccent.HRATestCenter.HRABusinessLayer.llblgen.DatePartExpressionTest.TestDatePart' failed: Object reference not set to an instance of an object. System.NullReferenceException: Object reference not set to an instance of an object. at SD.LLBLGen.Pro.DQE.SqlServer.SqlServerSpecificCreator.CreateFieldName(IFieldPersistenceInfo persistenceInfo, String fieldName, String objectAlias, Boolean appendAlias) at SD.LLBLGen.Pro.DQE.SqlServer.SqlServerSpecificCreator.CreateFieldName(IEntityFieldCore fieldCore, IFieldPersistenceInfo persistenceInfo, String fieldName, String objectAlias, Int32& uniqueMarker, Boolean applyAggregateFunction) p:\hraccentsolution\hraccentserver\hrabusinesslayer\llblgen\datepartexpression.cs(225,0): at HRAccent.BusinessLayer.Llblgen.DatePartExpression.OperandToText(StringBuilder& queryText, IExpressionElement operand, Int32& uniqueMarker, Boolean isLeftOperand, Boolean inHavingClause)

It crash when executing this line of code :

return string.Format("{0}", _creator.CreateFieldName(fieldCore, fieldElement.PersistenceInfo, fieldCore.Name, fieldCore.ObjectAlias, ref uniqueMarker, inHavingClause));

In debug mode, I see fieldElement.PersistenceInfo is null but : - I don't know why - I don't know how to fill it ?

The unit test using the expression :

public void TestDatePart() 
        {
            IExpression             expDatePart = new DatePartExpression(DatePartType.month, ExOp.None,  EntityFieldFactory.Create(EventFieldIndex.EvBegindate));
            IEntityField2           field       = EntityFieldFactory.Create(EventFieldIndex.EvBegindate);
            field.ExpressionToApply = expDatePart;
            
            IPredicate              expfilter   = new FieldCompareValuePredicate(field, null, ComparisonOperator.Equal, 10);
            
            RelationPredicateBucket filter      = new RelationPredicateBucket();
            filter.PredicateExpression.Add(expfilter);

            EntityCollection        ec          = new EntityCollection(new EventFactory());
            this.Context.Adapter.FetchEntityCollection(ec, filter);
            HRAccent.BusinessLayer.Process.DumpTools.DumpEventList(ec);
        }

Thanks for any help !

Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 23-Aug-2005 17:35:09   

groumf, bold and red in the code tag are not interpreted frowning

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 24-Aug-2005 10:05:27   

If you check out DataAccessAdapter.InsertPersistenceInfoObjects(expression), you'll see that the left operand is always a field or an expression. So the left operand requires persistence info always, the right operand only if it's not a value and if it's specified. I think you return from 'LeftOperand' null, which therefore doesnt make the persistence info for the field be set.

Frans Bouma | Lead developer LLBLGen Pro
Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 25-Aug-2005 11:04:37   

Yes it was because of the null leftoperand Thanks for the tip! Now it seem to work