RetrievalProcedures Changing Result Type

Posts   
 
    
willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 18-Nov-2012 08:06:02   

Hello, Using: LLBLGen Pro 3.5 Final Release Date: 11/6/12 Settings: Adapter and .NET 4.0

I just re-installed my computer so I installed updated to 3.5 from 3.1, I have this same issue even if I try going back to 3.1. I had a project that originally would generate this line of code for RetrievalProcedures:

public static DataTable MenuItemsNotAssignedToGroup(System.Int32 groupId, System.Int32 userId)

Now it keeps giving me:

public static DataSet MenuItemsNotAssignedToGroup(System.Int32 groupId, System.Int32 userId)

So Visual Studio generates this error: Cannot implicitly convert type 'System.Data.DataSet' to 'System.Data.DataTable' since my code was use to getting a DataTable not DataSet like so: DataTable resultSet = RetrievalProcedures.MenuItemsNotAssignedToGroup(GroupId, myUser.UserID, adapter);

I must be missing something... Why is it now a DataSet vs. DataTable, is it a setting? Thanks, Will

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 19-Nov-2012 03:50:10   

LLBLGen will generate a DataSet output if the stored procedure has more than 1 resultset, otherwise DataTable.

How many resultsets does have your SP? you can see that in Catalog Explorer: you expand your SP and then expand the Resulsets node.

David Elizondo | LLBLGen Support Team
willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 19-Nov-2012 05:09:33   

hmm. thank's for the response.

I see that in the Catalog Explorer it has two identical result sets. The Stored Procedure has not changed since the time before I had this problem. The SP accepts 2 parameters and returns only one resultset.

How can I test what llblgen is executing to get to the fact that it has 2 result sets? (using sql) I execute it in sql server mgmt studio and I only get one result set. Thanks, Will

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 19-Nov-2012 07:00:20   

When you refresh the catalog at LLBLGen Pro Designer, there is a step when LLBLGen is asking you to run the SP's to recover resulset information, that is where it detects the two resulsets. Additionally it will generate TypeView containers for the resultsets, if you want. So you can reverse engineer the SP call and the TypedView containers.

You can set them manually (the number of resulsets): Go and find your SP in Catalog, right click on it and click "Set number of resulsets" and click "1".

David Elizondo | LLBLGen Support Team
willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 20-Nov-2012 22:44:27   

I tried the "Set number of resultsets" and clicked 1. The code did not change in the retrievalProcedures after code-regenerate so I still get the convert type error. Thanks, Will

willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 20-Nov-2012 23:36:46   

and I'm back... I have a reason (sort of) of why this is happening.

My Stored Procedure has this type of logic:

If parm1 = 1 RUN SQL1 ELSE RUN SQL2 although both of the SQL statements return the same fields names, they select from different tables. It will only run one or the other SQL statements. If it received NULL it just exits.

If I comment out the ELSE SQL, llblgen says there is only 1 results set (vs. 2 identical ones). Somehow llblgen must be getting the schema or looking at the stored procedure code vs executing with NULL? (I read that that's how it does Oracle but I'm on SQL SERVER 2008 )

So I can't use IF statements if they execute different SELECT statements that could return results? Even if they are the save field names/definitions and not possible to return more than one resultset not matter what the parameter has?

-Will

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 21-Nov-2012 06:40:20   

Then maybe you should't use the step in the refresh catalog wizard that ask you to run the SPs. LLBLGen will run them with NULL params, Did you try that in your DB? LLBLGen doesn't look at your SP code.

Something you can do is comment that in your SP so LLBLGen can retrieve the resulset schema, then uncomment it and don't execute SPs in the next refreshes, that way you get the correct generated code.

David Elizondo | LLBLGen Support Team
willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 22-Nov-2012 04:45:59   

Well the work around for this problem is comment out, refresh, uncomment the IF procedures in the SP. This is a pain being how it wasn't a problem before and now it is. Maybe it's the SQL server 2008 R2. Anyway.....

To test that I wasn't crazy I did the following:

CREATE PROCEDURE [dbo].[returnnothing] as BEGIN GOTO ENDOFTHISSP SELECT * from sys.tables ENDOFTHISSP: END

Tested that no results could be returned by running the following: exec returnnothing No results returned. I even tried adding a parameter in case that made a difference and it didn't.

Next, refreshed the catalog in llblgen allowing it to execute the SP's.

Got a results set from llblgen as if the SQL had run even though it's not possible. See attached.

willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 22-Nov-2012 04:48:18   

I didn't attach the llblgen screenshot. o well it just showed the resultset with all the fields from the sql that couldn't have executed.

willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 22-Nov-2012 04:48:41   

here is the attachement

Attachments
Filename File size Added on Approval
Capture-returnnothing.PNG 19,151 22-Nov-2012 04:48.55 Approved
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 22-Nov-2012 14:15:53   

'Before' is presumably in v2.6? As in v3.0/3.1/3.5 it 'executes' (see below) the procs if you check the checkbox in the step David referred to, inside a transaction (which is rolled back) and passes 'null' as the parameter. It executes the procs as 'schemaonly', so it doesn't really run them. The datatable returned as the 'schema' is the resultset chosen. If there are multiple resultsets, it will simply obtain these using the same mechanism. It's below:


private bool ExecuteResultsetRetrievalQuery(DbConnection openConnection, DbCommand command, DBStoredProcedure storedProcedure, CommandBehavior behavior,
                                            string elementTypeName)
{
    bool succeeded = false;
    using(DbTransaction transaction = openConnection.BeginTransaction())
    {
        try
        {
            command.Transaction = transaction;
            using(DbDataReader reader = command.ExecuteReader(behavior))
            {
                int resultsetCounter = 1;
                reader.Read();
                DataTable metaData = reader.GetSchemaTable();
                DBStoredProcedureResultset toAdd = CreateResultsetFromSchemaTable(storedProcedure, metaData, resultsetCounter);
                if(toAdd != null)
                {
                    storedProcedure.AddResultset(toAdd);
                    while(reader.NextResult())
                    {
                        reader.Read();
                        metaData = reader.GetSchemaTable();
                        resultsetCounter++;
                        toAdd = CreateResultsetFromSchemaTable(storedProcedure, metaData, resultsetCounter);
                        if(toAdd != null)
                        {
                            storedProcedure.AddResultset(toAdd);
                        }
                    }
                }
                reader.Close();
            }
            succeeded = true;
        }
        catch(Exception ex)
        {
            // check if the behavior was SchemaOnly. if so, we'll silently ignore this exception as it will cause the caller to call this method again
            // with normal behavior. If the behavior wasn't schemaonly, this error isn't caused by schemaonly related issues so we've to report it and
            // ignore the proc. It still is a non fatal error, so skip the proc altogether
            if(behavior != CommandBehavior.SchemaOnly)
            {
                storedProcedure.ContainingSchema.LogError(ex, 
                        string.Format("{0} '{0}' caused an exception during resultset retrieval. Its resultsets (if any) probably aren't determined in full: {2}", 
                                elementTypeName, storedProcedure.Name, ex.Message), "DBSchemaRetriever::RetrieveResultsetsForStoredProcedure");
            }
            succeeded = false;
        }
        finally
        {
            transaction.Rollback();
        }
    }
    return succeeded;
}

I think sqlserver will simply report 2 resultsets for the proc, as the proc isn't executed in full so the 'if' doesn't run. In previous versions we did: SET FMTONLY ON; <run proc; SET FMTONLY OFF; but that could lead to problems with procs which called extended procs.

If you uncheck the checkbox, it won't retrieve the resultset for that proc and it will assume 0 resultsets. You then can set the # of resultsets to 1. If you keep the checkbox checked during refresh, it will pull the resultsets and changing the value has no real effect, as it still has 2 resultsets read.

Is this enough for your situation or do you need the typed resultset (and thus have to have the proc's checkbox checked during refresh) ?

Frans Bouma | Lead developer LLBLGen Pro
willg
User
Posts: 8
Joined: 18-Nov-2012
# Posted on: 22-Nov-2012 19:12:40   

Yes. 'before' does mean v2.6

I do use the typed result sets. I did do the comment out, refresh, un-comment and I'm moving along fine. I just wanted to see if there was something I was missing and honestly was trying to eliminate another step and make it easier for any future developers on my project. (vs. making notes somewhere that say 'you have to do this step first' and hope they find it) I could really split the SP's and change the code or generate some pre-build event in visual studio to pop-up a message or run some sql.

At least I have a solution and I can determine my plan of action going forward.

Thanks David and Frans for you help.