- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
DatePartExpression
Joined: 25-May-2004
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 !
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.