Strongly-typed datasets

Posts   
 
    
Posts: 12
Joined: 31-Aug-2007
# Posted on: 31-Aug-2007 19:43:18   

Hi, I'm currently evaluating ORM and DAL libraries.

I know LLBLGen uses custom entities. I would like to know if it's possible to use strongly-typed datasets instead.

AND I would like to know if it's possible to get strongly-typed datasets when calling a stored procedure wrapper. I know we can get a DataTable or a DataSet, but I don't know if they can be strongly-typed. (If not, that would be a very nice feature to have, using a generic method.)

(I don't have access to LLBLGen programmer reference - the doc files I downloaded from this site are broken.)

Thanks

DvK
User
Posts: 318
Joined: 22-Mar-2006
# Posted on: 31-Aug-2007 21:52:05   

Yes, you can use typedlists or typedviews and they return strongly-types rows. The INPUT-parameters of an SP are recognized by the designer, so they're "strong" as well.

Posts: 12
Joined: 31-Aug-2007
# Posted on: 31-Aug-2007 22:03:17   

Are they DataSets? I need to know not only if strong types are supported, but if strongly-typed DataSets themselves are supported. Thanks!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39870
Joined: 17-Aug-2003
# Posted on: 31-Aug-2007 22:15:06   
Frans Bouma | Lead developer LLBLGen Pro
Posts: 12
Joined: 31-Aug-2007
# Posted on: 31-Aug-2007 22:26:03   

OK, got the help to work.

Now, about the DataSets...? :-)

arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 31-Aug-2007 22:40:16   

You can certainly retrieve data into datasets using LlblGen. The core of the entities is not datasets and there is no check box to make them so.

Could you explain more about where you question is coming from and what you hope to accomplish? That would allow the users and support staff here to provide you with meaningful answers without needing to guess your intent.

If you are going down a checklist filling yes, yes, no, maybe for each bullet point, you are doing the ORMs you are looking at a disservice. No offense meant, but your questions seem of the "Have you stopped beating your children? Answer yes or no." variety.

Posts: 12
Joined: 31-Aug-2007
# Posted on: 31-Aug-2007 22:54:23   

We're currently using a simple DAL where we can call a Stored Procedure and get back a strongly-typed dataset.

Something like:

STDataSet mySTDataSet = MyStoredProcedure<STDataSet>(1, 2, 3);

But that DAL, doesn't answer all our needs, so we’re looking for a replacement.

In some specific solutions, we DO need strongly-typed datasets and NOT entities.

So I simply want to know if LLBLGen can do such a thing as return a strongly-typed DataSet from a stored procedure, and if not, if that feature is going to be included in a future release.

And what? - We can't post a question here without been flamed???

DvK
User
Posts: 318
Joined: 22-Mar-2006
# Posted on: 31-Aug-2007 22:55:01   

Please take a look at the manual for further info. A dataSet is nothing more than a collection of tables, and those tables (e.g. typed lists) can be addressed in a strongly typed manner as their rows contain fields as properties like a dataSet build within VS.

TypedLists are strongly typed and inherit from DataTable.

DvK
User
Posts: 318
Joined: 22-Mar-2006
# Posted on: 31-Aug-2007 22:59:53   

Isn't this mySTDataSet a predefined dataset within VS.net ? So strongly typed by itself ? An SP-call always returns a datatable or a dataset in case multiple resultsets are returned.

Posts: 12
Joined: 31-Aug-2007
# Posted on: 31-Aug-2007 23:05:29   

If you could provide me with a sample code for calling an SP with LLBLGen and filling a strongly-typed dataset, that would be very much appreciated. The only samples I've seen (in the few amount of time I spent with LLLGenPro) return a DataTabe and a DataSet (not strongly-typed versions of these).

STDataSet is a name I simply used for the sample :-)

With ADO.NET, you can call Fill on a dataset, but also on a strongly-typed dataset. So LLBLGEN could have a generic method which would return a strongly-typed ds rather than a typeless ds.

(I'm not a dataset fan, I've also used business entities here and there. It's just that our current solution requires datasets).

BTW: the llbgen sample I have is:

DataTable resultSet = RetrievalProcedures.CustOrderDetail(10254);

What I would like to know is if I could rather have something like, or equivalent to:

MyStronglyTypedDataTable resultSet = RetrievalProcedures<MyStronglyTypedDataTable>.CustOrderDetail(10254);

Thanks

DvK
User
Posts: 318
Joined: 22-Mar-2006
# Posted on: 31-Aug-2007 23:12:55   

I don't think it's even possible to return a strongly typed dataset from an SP as the resultset is dynamic by itself. LLBLGen cannot determine what the output schema(field=properties) will look like. If you merge/load the resultset into a strongly typed dataset though, designed using VS.net for example, you then have a strongly typed dataset.

DvK
User
Posts: 318
Joined: 22-Mar-2006
# Posted on: 31-Aug-2007 23:15:34   
With ADO.NET, you can call Fill on a dataset, but also on a strongly-typed dataset. So LLBLGEN could have a generic method which would return a strongly-typed ds rather than a typeless ds. 

->> Right, you're filling a predefined dataset here. Not a dataset which is being created at runtime, that can't be strongly typed as you'll need a code class (code behind the dataset) to make it strongly-typed.

Posts: 12
Joined: 31-Aug-2007
# Posted on: 31-Aug-2007 23:24:03   

Yes, you can do it. Generics resolution are part of the assemblies where they are used, not where they are defined. So, if I had a method like:

public T MySp<T>() where T : DataSet, new() { T ds = new T(); ...Fill(ds); return ds; }

in LLBGen, I could call it in my app and it would return the strongly-typed version of my dataset.

(Simply put, the type T would be known even if the method is in LLBGen, because it's resolved at the time my app is compiled.)

If you want to have some fun with generics, create a method like that in a dll, call it from another and open up ILDASM. You'll see that the method is in your second dll as well, strongly-typed with your type parameter wink

DvK
User
Posts: 318
Joined: 22-Mar-2006
# Posted on: 31-Aug-2007 23:30:36   

Otis, can you help him out ?? confused

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39870
Joined: 17-Aug-2003
# Posted on: 01-Sep-2007 10:49:04   

First of all, please keep it modest here (general remark, not towards any person in particular). simple_smile

Ok, on to the question.

Strongly typed datasets are just datasets with pre-defined columns and strongly typed datarow classes (and also a class derived from datatable). If you check TypedList classes, you'll see these look the same. The only difference is that typedlists can be filled with dyn. sql.

DevInstinct wrote:

If you could provide me with a sample code for calling an SP with LLBLGen and filling a strongly-typed dataset, that would be very much appreciated. The only samples I've seen (in the few amount of time I spent with LLLGenPro) return a DataTabe and a DataSet (not strongly-typed versions of these).

STDataSet is a name I simply used for the sample :-)

With ADO.NET, you can call Fill on a dataset, but also on a strongly-typed dataset. So LLBLGEN could have a generic method which would return a strongly-typed ds rather than a typeless ds.

(I'm not a dataset fan, I've also used business entities here and there. It's just that our current solution requires datasets).

BTW: the llbgen sample I have is:

DataTable resultSet = RetrievalProcedures.CustOrderDetail(10254);

What I would like to know is if I could rather have something like, or equivalent to:

MyStronglyTypedDataTable resultSet = RetrievalProcedures<MyStronglyTypedDataTable>.CustOrderDetail(10254);

Thanks

LLBLGen Pro has support for stored procedure CALLs, which means: you can call a stored procedure, passing parameters and if the proc returns a resultset, you will get back that resultset.

It doesn't perform a mapping of that resultset to a strongly typed structure, because that's pretty fragile: if the resultset changes, everything breaks at runtime.

Out of the box, there's not a routine which allows you to pass in a typed dataset and a proc and fill it. The reason is pretty simple: it has no additional value: the thing is that to create a typed dataset, you can also create tableadapters and other elements, which already do this for you.

If you want to, you of course could add a small template which generates this code for each retrieval proc into the generated code: this routine could then be used to fill your strongly typed datasets with proc calls created by llblgen pro.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 12
Joined: 31-Aug-2007
# Posted on: 04-Sep-2007 17:07:51   

Hi Otis,

That answers my question perfectly. I guess a custom template would be the way to do it.

Using a strongly-typed dataset (in a dataset scenario) has a lot of advantages. When you’re dealing with strict protocols, you DO want a runtime error to be thrown if a resultset changes. There are many ways of enforcing resultsets integrity - validating it against a strongly-typed dataset XML schema is one of them.

(I once implemented strongly-typed dataset support for stored procedures in an open source DAL, following user requests. So there is a need for that feature, in applications with datasets requirements.)

Thanks all for the fast replies!

Posts: 12
Joined: 31-Aug-2007
# Posted on: 04-Sep-2007 17:41:03   

Is there a way to check for a given type in the template language?

Something like:

<[If ProcedureOutputType Is DataTable]>my custom output code<[EndIf]>

(Where could I find the template reference? - I'm currently trying the demo version.)

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 05-Sep-2007 11:58:51   

<[ProcedureOutputType]> Will be replaced by the DataSet if the current stored procedure has more than 1 resultset, otherwise DataTable. Used in SqlServer templates, because SqlServer stored procedures can return multiple resultsets without cursors. Not used in Oracle templates for that reason. Used inside currentSPCall affecting loops.

Please download the LLBLGen Pro SDK manual.

Posts: 12
Joined: 31-Aug-2007
# Posted on: 05-Sep-2007 14:55:39   

I know that it can be DataTable or DataSet... this is exactly what I'm trying to change :-)

I want to replace them with a generic type-parameter, but have to know if i'm dealing with a DataTable or DataSet. So I need a way to check on the type with an if clause.

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 05-Sep-2007 15:59:58   

Do you want to perform this check on code generation, i.e. only generate the "my custom output code" code if the SP returns a DataSet?

Or you want to perform the check at runtime, i.e. generate the If condition, so the "my custom output code" code will be executed at runtime if the SP returns a DataSet?

Posts: 12
Joined: 31-Aug-2007
# Posted on: 05-Sep-2007 16:44:55   

Thanks again for the fast reply.

I want to do it at generation time. This is following the above discussion, so I'd like to generate something like:

(when output type is DataTable) public T MyStoredProc<T>(...) where T : DataTable, new() { }

or

(when output type is DataSet) public T MyStoredProc<T>(...) where T : DataSet, new() { }

Such code will enforce the type of the type-parameter I will use. Having the if condition will also help me to generate DataTable-specific or DataSet-specific method implementation (which I may need).

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39870
Joined: 17-Aug-2003
# Posted on: 06-Sep-2007 14:52:29   

(disclaimer, I haven't read the whole thread) Dataset's are only generated when the # of resultsets is > 1. Otherwise it's DataTable. So in the TDL, you can use: <[ProcedureOutputType]> to get either DataTable or DataSet. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 12
Joined: 31-Aug-2007
# Posted on: 06-Sep-2007 15:07:09   

Yes, but how can I set the "if" condition on the procedure output type at generation time?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39870
Joined: 17-Aug-2003
# Posted on: 07-Sep-2007 11:52:27   

Not with TDL (the template language our templates are mainly written in). We also support C#/VB.NET style templates though (similar to codesmith/mygeneration templates), with <% code%> style syntaxis. These are called .lpt templates (their extension is .lpt)

You can mix them in a single template set, and even use .lpt templates as include templates inside TDL templates. The TDL language is limited but it's mainly a DSL to write templates quickly with a fixed set of keywords which can be replaced by data. So if you want to do things other than what TDL provides, it can't do it, but it otherwise offers a fast way to write template code as it is easy to avoid bugs in the template code because all statements represent actually pieces of code you otherwise had to write in the template itself.

.lpt templates can access the complete object model which is the llblgen project and you can write the template code itself in vb.net or C# and emit any output you want. So in .lpt templates you can write a template which generates your generic class based on the # of resultsets of a stored proc call.

As .lpt templates work on the object model of the project, you need the SDK + reference manual in the SDK which describes the object model you are consuming in the .lpt template. The template system works with template binding files, which bind a template file to a templateID, the tasks run at generation time have a templateID specified for the template they need to use. They then look up the template file via the templatebindings used (which depends on language chosen, db type etc.) and then execute the template.

So to achieve what you want, you could: (example for Adapter, Sqlserver, .net 2.0) (see also: Using the generated code -> Adding your own code to the generated classes -> Include templates) Haven't tested this, but gives you the idea: - create a .lpt file, e.g. myRetrievalProcsInclude.lpt - add a line to Templates\SD.TemplateBindings.SqlServerSpecific.NET20.templatebindings, C# section: <templateBinding templateID="Custom_RetrievalProceduresAdapterTemplate" filename="SqlServerSpecific\Net2.x\C#\myRetrievalProcsInclude.lpt" /> (we normally recommend to create a new templatebindings file for that template alone or your own custom templates, but this will do for now. Our templatestudio editor makes this really easy) - to myRetrievalProcsInclude.lpt, which you've saved in Templates\SqlServerSpecific\Net2.x\C#\, add:


<%
SPCallContainer retrievalProcCalls = _executingGenerator.ProjectDefinition.RetrievalSPCalls;
foreach(SPCallDefinition retrievalProc in retrievalProcCalls)
{
    SPCallParameterCollection parameters = retrievalProc.Parameters;
    if(retrievalProc.AmountResultsets > 1)
    {
        // Dataset
%>  public T <%=retrievalProc.Name%><T>(<%...foreach over parameters %>) where T : DataSet, new()
{
    // your proc code
}<%
    }
    else
    {
        // datatable
    }
}%>

As you don't have the SDK nor template studio, you could check the object model with reflector (check SD.LLBLGen.Pro.ApplicationCore assembly, it's not obfuscated, and then the class 'Project' and the classes in the StoredProcedures namespace. The namespace is already added to the template so you can specify the classes as I did above.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 12
Joined: 31-Aug-2007
# Posted on: 07-Sep-2007 16:54:08   

Super, thanks!