Error converting data type when using ScalarQueryExpression

Posts   
 
    
ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 26-Jan-2007 00:13:13   

I get the following error when using the ScalarQueryExpression and paging results. Error converting data type nvarchar to bigint.

EntityField ef = new EntityField("Alias", new ScalarQueryExpression(FormAliasFields.Alias, (FormAliasFields.WorkflowInstanceId == FormStateTrackingFields.WorkflowInstanceId & FormAliasFields.UserId == UserInboxFields.UserId)));

The alias field is an nvarchar but the SQL generated has [Alias][BigInt] NULL in the temp table. I tried to see if there was a way to force the Field to a certain type, but I could not figure it out.

I am using 2.0.0.0 Final with the runtime versions 2.0.0.61220

Here is the stace trace from where things started going wrong. [SqlException (0x80131904): Error converting data type nvarchar to bigint.] System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +857418 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +735030 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +188 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1838 System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +31 System.Data.SqlClient.SqlDataReader.get_MetaData() +62 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +297 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +886 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +132 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +122 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12 System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) +7 System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) +141 System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior) +162 System.Data.Common.DbDataAdapter.Fill(DataTable dataTable) +107 SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.ExecuteMultiRowDataTableRetrievalQuery(IRetrievalQuery queryToExecute, DbDataAdapter dataAdapterToUse, DataTable tableToFill, IEntityFields fieldsToReturn) +645 SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.PerformGetMultiAsDataTableAction(IEntityFields fieldsToReturn, DataTable tableToFill, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IPredicate selectFilter, IRelationCollection relations, Boolean allowDuplicates, IGroupByCollection groupByClause, ITransaction transactionToUse, Int32 pageNumber, Int32 pageSize) +174 AG.Forms.DAL.DaoClasses.TypedListDAO.GetMultiAsDataTable(IEntityFields fieldsToReturn, DataTable tableToFill, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IPredicate selectFilter, IRelationCollection relations, Boolean allowDuplicates, IGroupByCollection groupByClause, ITransaction transactionToUse, Int32 pageNumber, Int32 pageSize) in J:\Development\SpectrumModules\src\AG.Forms.DAL\DaoClasses\TypedListDAO.cs:49 AG.Forms.Tasks.FormStateTrackingTask.GetFormListForUser(Int32 userID, String formState, Int32 pageIndex, Int32 pageSize, Int32& recordCount) in D:\Austin\Devel\SpectrumModules\src\AG.Forms\Tasks\FormStateTrackingTask.cs:63

We are using SQL server 2005 and have the SqlServerDQECompatibilityLevel set to 2.

Any help would be welcomed.

Thanks.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 26-Jan-2007 08:26:14   

Would you please post the complete code where the ScalarQueryExpression is used?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 26-Jan-2007 10:49:34   

Could you also switch on tracing and post the SQL query generated?

Frans Bouma | Lead developer LLBLGen Pro
ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 26-Jan-2007 19:18:52   

Here is the code.

public DataTable GetFormListForUser(int userID, string formState, int pageIndex, int pageSize, out int recordCount) {

        SortExpression sort = new SortExpression();
        sort.Add(new SortClause(FormStateTrackingFields.RecordCreationDate, SortOperator.Descending));

        DataTable dt = new DataTable();
        TypedListDAO dao = new TypedListDAO();
        recordCount = 0;
        recordCount = GetFormListCountForUser(userID, formState);
        dao.GetMultiAsDataTable(UserFormListFields, dt, 0, sort, GetUserFormListFilter(userID, formState), UserFormListRelations, false, null, null, pageIndex, pageSize);
        return dt;
    }

private ResultsetFields UserFormListFields { get { ResultsetFields fields = new ResultsetFields(7); fields.DefineField(WorkflowInstanceFields.WorkflowInstanceInternalId, 0); fields.DefineField(FormStateTrackingFields.FormStateTrackingId, 1); fields.DefineField(FormFields.FormName, 2); fields.DefineField(FormStateTrackingFieldIndex.TargetState, 3, "Status"); fields.DefineField(FormStateTrackingFields.WorkflowInstanceId, 4); fields.DefineField(FormStateTrackingFieldIndex.RecordCreationDate, 5, "LastAction");

            EntityField ef = new EntityField("Alias",
                new ScalarQueryExpression(FormAliasFields.Alias,
                    (FormAliasFields.WorkflowInstanceId == FormStateTrackingFields.WorkflowInstanceId &
                    FormAliasFields.UserId == UserInboxFields.UserId)));

            fields.DefineField(ef, 6);


            fields["Status"].ExpressionToApply = new DbFunctionCall("FormTracking", "Form", "GetLastTargetState", new object[] { FormStateTrackingFields.WorkflowInstanceId });

            return fields;
        }
    }

Here is the SQL from SQL Profiler.

exec sp_executesql N'CREATE TABLE #TempTable ([__rowcnt][int] IDENTITY (1,1) NOT NULL,[WorkflowInstanceInternalId][BigInt] NULL,[FormStateTrackingId][BigInt] NULL,[FormName]NVarChar NULL,[Status]NVarChar NULL,[WorkflowInstanceId][UniqueIdentifier] NULL,[LastAction][DateTime] NULL,[Alias][BigInt] NULL);INSERT INTO #TempTable ([WorkflowInstanceInternalId],[FormStateTrackingId],[FormName],[Status],[WorkflowInstanceId],[LastAction],[Alias]) SELECT DISTINCT TOP 11 [FormTracking].[dbo].[WorkflowInstance].[WorkflowInstanceInternalId], [FormTracking].[Form].[FormStateTracking].[FormStateTrackingID] AS [FormStateTrackingId], [FormTracking].[Form].[Form].[FormName], [FormTracking].[Form].GetLastTargetState([FormTracking].[Form].[FormStateTracking].[WorkflowInstanceID]) AS [Status], [FormTracking].[Form].[FormStateTracking].[WorkflowInstanceID] AS [WorkflowInstanceId], [FormTracking].[Form].[FormStateTracking].[RecordCreationDate] AS [LastAction], (SELECT TOP 1 [FormTracking].[Form].[FormAlias].[Alias] FROM [FormTracking].[Form].[FormAlias] WHERE ( [FormTracking].[Form].[FormAlias].[WorkflowInstanceID] = [FormTracking].[Form].[FormStateTracking].[WorkflowInstanceID] AND [FormTracking].[Form].[FormAlias].[UserID] = [FormTracking].[Form].[UserInbox].[UserID])) AS [Alias] FROM ((((( [FormTracking].[Form].[UserInbox] INNER JOIN [FormTracking].[Form].[FormStateTracking] ON
[FormTracking].[Form].[UserInbox].[FormStateTrackingID]=[FormTracking].[Form].[FormStateTracking].[ FormStateTrackingID]) INNER JOIN [FormTracking].[Form].[FormVersion] ON
[FormTracking].[Form].[FormVersion].[FormVersionID]=[FormTracking].[Form].[FormStateTracking].[FormVersionID]) INNER JOIN [FormTracking].[Form].[Form] ON
[FormTracking].[Form].[Form].[FormID]=[FormTracking].[Form].[FormVersion].[FormID]) INNER JOIN [FormTracking].[dbo].[WorkflowInstance] ON
[FormTracking].[dbo].[WorkflowInstance].[WorkflowInstanceId]=[FormTracking].[Form].[ FormStateTracking].[WorkflowInstanceID]) LEFT JOIN [FormTracking].[Form].[FormAlias] ON
[FormTracking].[Form].[FormAlias].[WorkflowInstanceID]=[FormTracking].[Form].[FormStateTracking].[WorkflowInstanceID]) WHERE ( ( [FormTracking].[Form].[UserInbox].[UserID] = @UserId1 AND [FormTracking].[Form].[UserInbox].[Archived] = @Archived2 AND [FormTracking].[Form].[FormStateTracking].[TargetState] = @TargetState3)) ORDER BY [FormTracking].[Form].[FormStateTracking].[RecordCreationDate] DESC;SELECT [WorkflowInstanceInternalId],[FormStateTrackingId],[FormName],[Status],[WorkflowInstanceId],[LastAction],[Alias] FROM #TempTable WHERE [__rowcnt] > @__rownoStart AND [__rowcnt] <= @__rownoEnd ORDER BY [__rowcnt] ASC;DROP TABLE #TempTable',N'@UserId1 int,@Archived2 bit,@TargetState3 nvarchar(30),@__rownoStart int,@__rownoEnd int',@UserId1=260771,@Archived2=0,@TargetState3=N'savedstate',@__rownoStart=5,@__rownoEnd=10

Notice that the Alias column in the Temp Table is a BigInt, but the Column type is nvarchar.

Let me know if more information is needed.

ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 26-Jan-2007 19:36:20   

I forgot some peices of code. Here are the Relations and the Filter.

private IRelationCollection UserFormListRelations { get { IRelationCollection relations = new RelationCollection(); relations.Add(new EntityRelation(UserInboxFields.FormStateTrackingId, FormStateTrackingFields.FormStateTrackingId, RelationType.OneToMany)); relations.Add(FormVersionEntity.Relations.FormStateTrackingEntityUsingFormVersionId, JoinHint.Inner); relations.Add(FormEntity.Relations.FormVersionEntityUsingFormId, JoinHint.Inner); relations.Add(new EntityRelation(WorkflowInstanceFields.WorkflowInstanceId, FormStateTrackingFields.WorkflowInstanceId, RelationType.OneToMany)); EntityRelation r = new EntityRelation(FormAliasFields.WorkflowInstanceId, FormStateTrackingFields.WorkflowInstanceId, RelationType.OneToMany); relations.Add(r, JoinHint.Left);

            return relations;
        }

    }

private IPredicateExpression GetUserFormListFilter(int userID, string formState) { bool isSubmit = (formState.Contains("submit"));

        //// filter
        IPredicateExpression filter = new PredicateExpression();
        filter.Add(UserInboxFields.UserId == userID);
        filter.AddWithAnd(UserInboxFields.Archived == false);

        // Submitted or saved?
        if (isSubmit)
        {
            filter.AddWithAnd((FormStateTrackingFields.IsSubmit == 1));
        }
        else
        {
            filter.AddWithAnd(FormStateTrackingFields.TargetState == formState);
        }

        return filter;
    }
Chester
Support Team
Posts: 223
Joined: 15-Jul-2005
# Posted on: 28-Jan-2007 18:21:31   

I see the following column definitions that are confusing to me:

WorkflowInstanceInternalId bigint WorkflowInstanceId uniqueidentifier

This of course is according to the TEMP table created. What are these columns defined as in your database?

ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 29-Jan-2007 17:00:01   

Chester wrote:

I see the following column definitions that are confusing to me:

WorkflowInstanceInternalId bigint WorkflowInstanceId uniqueidentifier

This of course is according to the TEMP table created. What are these columns defined as in your database?

In my database the WorkflowInstanceID is stored as a UniqueIdentifier and the WorkflowInstanceInternalId is stored as an auto incrementing BigInt.

The Alias Field is stored as an NVarchar(100), but is a BigInt in the temp table.

I hope this helps to find the issue. Thanks.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 30-Jan-2007 09:06:30   

I'm sorry about this but I need to replicate or reproduce the query you are executing but I need to understand what exactly you are trying to do, and why the use of the ScalarQueryExpression and the entire dynamic list.

So would you please describe the involved tables structures and the SQL Query you want to execute?

ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 31-Jan-2007 06:38:07   

I have created a test project. This includes the DAL project and a new class project with all the code that causes the issue. The Runtime libraries that I am using are in the lib folder and are used by all the projects I have also created uint tests that show it working when not paging and then failing when paging. It only fails when that data coming back in the Alias Column are nvarchar types. I inlcuded the DB (with most data stripped) and a sample restore script that will restore it if you replace the <path> placholders with proper paths in the db folder.

In the app.config file in the unit test project you can change the connection string and the catalog overwrites.

I hope this help to track down the problem.

Thanks.

ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 31-Jan-2007 06:44:54   

I could not upload the attachment cause it is too big. Is there any other way for me to get this to you? its 7.4 MB. I cleaned up the DB as much as I could and packed down the solution after removing all the bin and obj folders.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 31-Jan-2007 08:07:21   

ecirpnaes wrote:

I could not upload the attachment cause it is too big. Is there any other way for me to get this to you? its 7.4 MB. I cleaned up the DB as much as I could and packed down the solution after removing all the bin and obj folders.

You can mail it to support AT llblgen.com. Be sure you explain what is expected and what is happening instead.

Frans Bouma | Lead developer LLBLGen Pro
ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 31-Jan-2007 23:24:41   

Email has beent sent.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 01-Feb-2007 08:36:33   

ecirpnaes wrote:

Email has beent sent.

I received it. I'll look into it this morning.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 01-Feb-2007 12:34:38   

The problem is that the ScalarQueryExpression has a return type which is unknown to the query generator, as that would require expression execution on the server to be certain. You can help it though, by using a trick: set the scalarqueryexpression as the expression of a field which has the proper returntype, i.e. the Alias field:


EntityField ef = FormAliasFields.Alias.SetExpression(
    new ScalarQueryExpression(FormAliasFields.Alias,
        (FormAliasFields.WorkflowInstanceId == FormStateTrackingFields.WorkflowInstanceId &
        FormAliasFields.UserId == UserInboxFields.UserId))).SetFieldAlias("Alias");

This solves your problem.

The reason it uses a temptable, is that it has to as the ROW_NUMBER() query will probably result in incorrect results, due to the risk on duplicates because of the relations specified.

The only way to generate a ROW_NUMBER() query that works is by doing it all in a big routine, as every table / resultset inside the queries has to be re-aliased, which is cumbersome if the query generation is outsourced to objects which make up the query (i.e. like OO prescribes wink ). As there's already a way to obtain the right rows, i.e the temptable approach, it switches behind the scenes to the temptable approach if it needs to.

It's still unbelievable why microsoft didnt' simply implement a simple SKIP n FETCH y solution in SELECT...

Frans Bouma | Lead developer LLBLGen Pro
ecirpnaes
User
Posts: 21
Joined: 22-Oct-2005
# Posted on: 01-Feb-2007 16:25:42   

Thanks this is exactly what I was looking for.