DbSpecificCreatorBase.CreateParameterName no longer virtual

Posts   
 
    
wadec
User
Posts: 2
Joined: 25-Feb-2017
# Posted on: 25-Feb-2017 00:49:00   

We are in the process of migrating from LLBLGen 4.2 to 5.1.2.

In our code we are overriding the CreateParameterName() in SD.LLBLGen.Pro.ORMSupportClasses.DbSpecificCreatorBase.

It seems that this was possible up until 5.0.9. Then in 5.1.0 then virtual keyword was removed.

Our project relies on the ability to override these parameter names.

Can you please check to see if this was removed in error.

Thanks

WadeC

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 25-Feb-2017 09:54:37   

The virtual method was not needed, and it wasn't clear what use case it had, so we removed it. Not all code paths called that method, so it was actually a badly designed method. Could you elaborate on why you need to override the parameter names? Perhaps there's a different way to accomplish what you want simple_smile

Frans Bouma | Lead developer LLBLGen Pro
wadec
User
Posts: 2
Joined: 25-Feb-2017
# Posted on: 01-Mar-2017 23:38:18   

The original reason for us using overriding the CreateParameterName predates me but this after investigating I have found out that the goal was to force some parameters in an Oracle query to be Date instead of DateTime.

Our generated SQL for our Oracle DB is:

WHERE ( ("START_TIME" < : p1 AND ("START_TIME" + "DURATION" / 24) > : p3))

Parameter: p1 : Date. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: 3/3/2017 8:00:00 AM.

Parameter: p3 :** DateTime**. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: 2017-03-02T08:00:00.0000000.

We would like p3 to be generated with a Date type … similar to p1.

In order to do this we used our own OracleSpecificCreator that grabbed all DB.DateTime types and switched them to Date. The CreateParameterName was used because our parameters where generated with our custom PredicateExpression which resulted in its own parameter numbering. The parameters we generated in our custom classes ended up reusing the p sequence – resulting in parameters named p1, p2, etc and a naming conflict with parameters generated outside of our custom classes. This was resolved by using the CreateParameterName to prefix the parameter with a unique string.

(Sorry for the long explanation)

But … I think I can throw all these custom classes away if I can figure out a fix to the original problem – How can we force a generated parameter from a predicate to be a certain type?

Our predicate for p3 is:

filter.AddWithAnd(new EntityField2("EndTime", ShapeFields.StartTime + new Expression(ShapeFields.Duration, ExOp.Div, 24)) > hourDateTime);

I have tried adding a dataType parameter to the EntityField2 constructor … but that made no difference.

Thanks,

WadeC

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 03-Mar-2017 11:08:38   

ODP.NET maps the Date type to a .NET DateTime, so it has to be set explicitly, it won't pick 'Date' based on the .NET type. When comparing to a Date typed field, the value will be typed 'Date' as well, but with an expression, as in your case, the value is passed as-is, and ODP.NET types it 'datetime' instead. The type you see in the trace is the DbParameter.DbType value btw, not the Oracle type (as Oracle doesn't have a DateTime type). The parameter has the type 'Timestamp', which is also a type mapping to DateTime, and not what you want indeed.

We can't change that as there's a use case to want to have a Timestamp type.

For you to change it, you have to override DetermineDbTypeNameForValue in the OracleSpecificCreator derived class you already have. First call the base method to create the parameter.

It returns a string which is used as a key into a set of pre-compiled, IL generated OracleDbType enum retrievers (as they're built by reflection as the OracleDbType enum isn't known at compile time). By default, a value of type 'DateTime' will return 'TimeStamp', and the value passed in as the realValueToUse (as no conversion is needed).

What you could do in your override of this method is to test first whether the passed in value is a DateTime. If not, simply call the base method. If it is, test whether there's a time fragment in your passed in value. If there is, call the base method, otherwise return "Date" (and the value passed in as realValueToUse). That should be it to fix it simple_smile

Frans Bouma | Lead developer LLBLGen Pro