How to make a template do anything?

Posts   
 
    
Posts: 6
Joined: 16-Aug-2017
# Posted on: 17-Aug-2017 21:45:59   

I've searched the forum and the internet and can't find any instructions oh how to get a lpt template to generate a file or how it knows that the _activeObject is or any documentation at all about anything template related other than how to add the template in the template viewer.

Since you can't build DTO objects correctly I'm trying to find a way to do it without feeding the llblgen project file to xslt or something else. All I want is a partial class for each DTO entity were I can add the Navigation properties without redefining the related types every time.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39570
Joined: 17-Aug-2003
# Posted on: 18-Aug-2017 09:30:00   

VoyagerSystems wrote:

I've searched the forum and the internet and can't find any instructions oh how to get a lpt template to generate a file or how it knows that the _activeObject is or any documentation at all about anything template related other than how to add the template in the template viewer.

You've looked at the SDK docs? https://www.llblgen.com/Documentation/5.2/SDK/gettingstarted.htm

Since you can't build DTO objects correctly I'm trying to find a way to do it without feeding the llblgen project file to xslt or something else.

What do you mean exactly with 'since you can't build DTO objects correctly?

All I want is a partial class for each DTO entity were I can add the Navigation properties without redefining the related types every time.

Could you give an example what you mean with 'add the navigation properties' ? As the DTOs already contain those.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 6
Joined: 16-Aug-2017
# Posted on: 18-Aug-2017 15:00:46   

Otis wrote:

VoyagerSystems wrote:

I've searched the forum and the internet and can't find any instructions oh how to get a lpt template to generate a file or how it knows that the _activeObject is or any documentation at all about anything template related other than how to add the template in the template viewer.

You've looked at the SDK docs? https://www.llblgen.com/Documentation/5.2/SDK/gettingstarted.htm

Yeas and I've read https://www.llblgen.com/Documentation/5.2/SDK/templates_lpt.htm

It's generating a class for my template, I only know this because it errors if I intentionally introduce a syntax error. Beyond the mention of IGenerator it tells you almost nothing. For example it includes this: "(if for example the emitType is set to allEntities, the active object is the current EntityDefinition.)" emitType? Whats that? Were do I set it in the designer? It implies I can make my template only apply to one type of entity. Or something even more mundane. How do I specify the output file name? I tells me how to specify the name of the template class though.

Otis wrote:

Since you can't build DTO objects correctly I'm trying to find a way to do it without feeding the llblgen project file to xslt or something else.

What do you mean exactly with 'since you can't build DTO objects correctly?

https://www.llblgen.com/documentation/5.2/Derived%20Models/dto_nh.htm

Otis wrote:

All I want is a partial class for each DTO entity were I can add the Navigation properties without redefining the related types every time.

Could you give an example what you mean with 'add the navigation properties' ? As the DTOs already contain those.

No they don't. They generate a brand new data type. https://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=24330 I want something like this exactly mirroring the data types in the model.


namespace DTO.DtoClasses
{
    public partial class Event
    {
        public ISet<EventState> EventStates { get; set; }

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39570
Joined: 17-Aug-2003
# Posted on: 18-Aug-2017 20:34:20   

First a blunt remark: I would appreciate it if you change your tone. If you want to vent here, I have to disappoint you: this isn't the place for that. If you want us to help you, please be more friendly. Ok?

VoyagerSystems wrote:

Otis wrote:

VoyagerSystems wrote:

I've searched the forum and the internet and can't find any instructions oh how to get a lpt template to generate a file or how it knows that the _activeObject is or any documentation at all about anything template related other than how to add the template in the template viewer.

You've looked at the SDK docs? https://www.llblgen.com/Documentation/5.2/SDK/gettingstarted.htm

Yeas and I've read https://www.llblgen.com/Documentation/5.2/SDK/templates_lpt.htm

It's generating a class for my template, I only know this because it errors if I intentionally introduce a syntax error. Beyond the mention of IGenerator it tells you almost nothing. For example it includes this: "(if for example the emitType is set to allEntities, the active object is the current EntityDefinition.)" emitType? Whats that? Were do I set it in the designer? It implies I can make my template only apply to one type of entity. Or something even more mundane. How do I specify the output file name? I tells me how to specify the name of the template class though.

The SDK is more than just that page. emitType is a parameter of the task performer used, e.g. : https://www.llblgen.com/Documentation/5.2/SDK/shipped_taskperformers.htm#codeemitter

You run a preset, a preset contains the definitions of which tasks to run with which parameters. Per task a task performer is executed, with the parameters defined in the preset (or the default values defined in the task definition if no value is specified in the preset). One of the parameters can be a templateID. The templateID is bound to a file through a templatebindings file.

That's how the things relate to each other. The SDK has documentation on each of these.

To run a template, you thus have to define a task in the preset you want to run, e.g. by copying one already there and e.g. change the templateID to the templateID bound to the template you want to run.

Otis wrote:

Since you can't build DTO objects correctly I'm trying to find a way to do it without feeding the llblgen project file to xslt or something else.

What do you mean exactly with 'since you can't build DTO objects correctly?

https://www.llblgen.com/documentation/5.2/Derived%20Models/dto_nh.htm

Sorry, but that's a page in our docs. I don't see how that answers my question. I asked you a question what you meant by that, and I do that because I want to know the answer so I can better help you. If you then point me to a page in the docs without any further comment, I then have to assume I have to puzzle out myself what you meant.

I then don't really know how that helps me help you.

Otis wrote:

All I want is a partial class for each DTO entity were I can add the Navigation properties without redefining the related types every time.

Could you give an example what you mean with 'add the navigation properties' ? As the DTOs already contain those.

No they don't. They generate a brand new data type. https://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=24330 I want something like this exactly mirroring the data types in the model.


namespace DTO.DtoClasses
{
    public partial class Event
    {
        public ISet<EventState> EventStates { get; set; }

They create new datatypes for DTOs projected from entities indeed. The main reason is that the DTOs are projections of entities, not the entities themselves: you can leave out fields, you can denormalize fields from related DTOs into a DTO so they're different types. See it as a hierarchy / graph projected from an entity hierarchy. Even if you simply project all entity fields, they're still not the same types. You shouldn't want that either for the reasons above, but also because of boundaries: the types in the DTO space are not interchangeable with the entity types, even if they look like it. If you forcefully re-use them, a change to the DTOs which makes sense in the DTO space, is then present in the entities as well, and vice versa.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 6
Joined: 16-Aug-2017
# Posted on: 18-Aug-2017 23:36:31   

Otis wrote:

First a blunt remark: I would appreciate it if you change your tone. If you want to vent here, I have to disappoint you: this isn't the place for that. If you want us to help you, please be more friendly. Ok?

I asked "I've searched the forum and the internet and can't find any instructions oh how to get a lpt template to generate a file" You stated "You've looked at the SDK docs?" Instead of something like "You need to create a Preset , see section blah of the manual." How about we both work on moderating our tone.

Otis wrote:

You run a preset, a preset contains the definitions of which tasks to run with which parameters. Per task a task performer is executed, with the parameters defined in the preset (or the default values defined in the task definition if no value is specified in the preset). One of the parameters can be a templateID. The templateID is bound to a file through a templatebindings file.

That's how the things relate to each other. The SDK has documentation on each of these.

To run a template, you thus have to define a task in the preset you want to run, e.g. by copying one already there and e.g. change the templateID to the templateID bound to the template you want to run.

I skipped the presets section entirely. There's no reference to it in the templates section. I'll have to read it. It sounded like adding my template to an existing TemplateBindings was the way to go.

Otis wrote:

Sorry, but that's a page in our docs. I don't see how that answers my question. I asked you a question what you meant by that, and I do that because I want to know the answer so I can better help you. If you then point me to a page in the docs without any further comment, I then have to assume I have to puzzle out myself what you meant.

I then don't really know how that helps me help you.

The docs state the DTO persistence can't handle inheritance. So I need to use/make one that will. I'm not expecting help with that here.

Otis wrote:

They create new datatypes for DTOs projected from entities indeed. The main reason is that the DTOs are projections of entities, not the entities themselves: you can leave out fields, you can denormalize fields from related DTOs into a DTO so they're different types. See it as a hierarchy / graph projected from an entity hierarchy. Even if you simply project all entity fields, they're still not the same types. You shouldn't want that either for the reasons above, but also because of boundaries: the types in the DTO space are not interchangeable with the entity types, even if they look like it. If you forcefully re-use them, a change to the DTOs which makes sense in the DTO space, is then present in the entities as well, and vice versa.

What I want is to use the same DTO type in two different projections because OData will let me get an arbitrary graph from one controller and post edits to node to another controller. So the DTO types need to be roots with navigation properties to each other as appropriate for the inter DTO relationships.

Otherwise the client will have to re-request every entity in the hierarchy in order to edit it. And after editing it re-request the entirety of the first graph to get the updates.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 19-Aug-2017 06:11:03   

Hi there,

In order to guide you to the process to obtain the desired output, please tell us:

  • A simple example of your graph structure
  • What is what you get generated with the actual preset for DTO?
  • What is what you really want to be generated in your DTOs.

This way we can evaluate what is built and what could/should be changed in your custom template so you can override the current one in the generation process.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39570
Joined: 17-Aug-2003
# Posted on: 19-Aug-2017 09:52:48   

VoyagerSystems wrote:

Otis wrote:

First a blunt remark: I would appreciate it if you change your tone. If you want to vent here, I have to disappoint you: this isn't the place for that. If you want us to help you, please be more friendly. Ok?

I asked "I've searched the forum and the internet and can't find any instructions oh how to get a lpt template to generate a file" You stated "You've looked at the SDK docs?" Instead of something like "You need to create a Preset , see section blah of the manual."

You stated you searched high and low and apparently didn't read the SDK docs. That's fine, but the topic isn't a small 2-liner. I can repeat what's in the SDK docs here, I can also point you to it (as it's a lot) as it's not something you can write down in 2 lines of text. So I chose the latter simple_smile

How about we both work on moderating our tone.

Let me be blunt again: you don't tell me what to do on our forums. If you want support, you simply be nice, as we will be nice too. Your post didn't start friendly and it didn't continue friendly at all. I don't mind if people are angry because something failed, or crashes, or is badly designed in their eyes, or complex, if we can improve things, we always want to know where/how. I know I'm not the friendliest when I run into issues with e.g. vs, .net etc. too, and that's fine. But there's a time when that ends and the person I talk to has to help me, and that won't work if I stay angry. Here, the roles are reversed and I draw the line where the people who want support but are angry think they have to tell me to lighten up too.

Ok?

Otis wrote:

You run a preset, a preset contains the definitions of which tasks to run with which parameters. Per task a task performer is executed, with the parameters defined in the preset (or the default values defined in the task definition if no value is specified in the preset). One of the parameters can be a templateID. The templateID is bound to a file through a templatebindings file.

That's how the things relate to each other. The SDK has documentation on each of these.

To run a template, you thus have to define a task in the preset you want to run, e.g. by copying one already there and e.g. change the templateID to the templateID bound to the template you want to run.

I skipped the presets section entirely. There's no reference to it in the templates section. I'll have to read it. It sounded like adding my template to an existing TemplateBindings was the way to go.

No but there is in the general documentation, under 'how to work with templates': https://www.llblgen.com/Documentation/5.2/Designer/How%20Toworkwithtemplates.htm

Anyway, it's a complex topic, and if you start at the bottom with one part, it might look like how it ever fits into the grander machinery.

Otis wrote:

Sorry, but that's a page in our docs. I don't see how that answers my question. I asked you a question what you meant by that, and I do that because I want to know the answer so I can better help you. If you then point me to a page in the docs without any further comment, I then have to assume I have to puzzle out myself what you meant.

I then don't really know how that helps me help you.

The docs state the DTO persistence can't handle inheritance. So I need to use/make one that will. I'm not expecting help with that here.

That wasn't that hard, was it? simple_smile No it indeed doesn't handle inheritance because that doesn't work in practice: you can't create a query projecting to DTOs with inheritance, where related subtypes are projected to different DTOs. This only works with entities which have mappings as subtypes so the ORM knows which type to pick per row by analyzing the data in the row. Projecting to DTOs doesn't work like that: you have a row and you project to a type, you can't determine at that moment which type to choose. Trust me, we tried. (see link below too, of code that was generated with code we had but in the end wasn't reliable as all ORMs except our own failed with even the most simple setup)

In theory you can, with a union linq query and fetch all types in separate queries and union them together but that's seriously slow, and fetching related data won't work with subtypes at all. Researching this to see whether others had found a way we saw it was tried on Automapper as well and there too it doesn't work. We don't know of a way to do it without serious issues (and again, in most cases the ORM simply throws an error due to the way the projection needs to be set up and it can't execute the query), so we don't support it.

(edit) Here's an example of what we had: https://github.com/AutoMapper/AutoMapper/issues/570#issuecomment-140053837

used as an example of what in theory seems to be possible, but in practice it fails in most cases inside the ORM (and NH's linq provider definitely failed with this).

Otis wrote:

They create new datatypes for DTOs projected from entities indeed. The main reason is that the DTOs are projections of entities, not the entities themselves: you can leave out fields, you can denormalize fields from related DTOs into a DTO so they're different types. See it as a hierarchy / graph projected from an entity hierarchy. Even if you simply project all entity fields, they're still not the same types. You shouldn't want that either for the reasons above, but also because of boundaries: the types in the DTO space are not interchangeable with the entity types, even if they look like it. If you forcefully re-use them, a change to the DTOs which makes sense in the DTO space, is then present in the entities as well, and vice versa.

What I want is to use the same DTO type in two different projections because OData will let me get an arbitrary graph from one controller and post edits to node to another controller. So the DTO types need to be roots with navigation properties to each other as appropriate for the inter DTO relationships.

Otherwise the client will have to re-request every entity in the hierarchy in order to edit it. And after editing it re-request the entirety of the first graph to get the updates.

In theory that could work, in practice it will be very brittle as every derived element is unique. So if you e.g. have Category->Product and OrderLine->Product, you have in theory 1 type 'Product', but you can have different fields in each of them, even though they're derived from the same entity. Because of this, it's not recommended to assume every dto derived from an entity E is the same, as changing it will affect all dtos in the model, which is precisely not the point of having it in the first place: DTOs are potentially denormalized, and as they're projections, type sharing like in entity models, isn't present. That's also why there aren't relationships, a related type is unique to that graph.

In your situation, it's likely best to simply return entity graphs instead, not DTOs, as you don't need a projection of the graphs: OData will already create that at its surface area anyway.

Frans Bouma | Lead developer LLBLGen Pro