Forum:  Custom Templates

Thread:  Moving from 3.1 to 4.2 - Templates?

jg (User)   Posted on: 18-Nov-2015 16:44:41.
We've been on LLBLGen 3.1 and need to move to a newer version, to support SQL Server 2014. We're attempting to go with 4.2, but we have the problem that this was set up so long ago, that no one in the company is really an LLBLGen expert. I'm trying to make this happen, but I'm probably missing something pretty basic.

I'm attempting to add 2 tables and a View, and there are updates to some stored procedures that were already in the model. We had been deploying the dacpac to a 2008 SQL server, but some modifications to stored procedures that have been made dictate that we can no longer do that. Our Production SQL servers are 2014. So, that's the impetus to use moving to LLBLGen 4.2.

The essential problem is that "out of the box" isn't working. The EntitySubClasses, TypedViewClasses, and ValidatorClasses folders aren't being created, so we're missing the classes under them. Previously, when we moved to 3.1, I think, we were missing the piece where we needed to use the Preset value "SD.Presets.Adapter.TwoClasses2010", and that caused a similar problem.

In 4.2, if I change the Template Group to "SelfServicing", that allows me to use the Selected Preset value "SD.Presets.SelfServicing.TwoClasses". But, that doesn't seem to be the same thing at all.

Using the "Adapter" Template Group, it seems very close to what we had before, but we don't have a "TwoClasses" Preset, and I'm unsure of what all would need to be changed to match that.

I am using .NET 4.5.1, and I basically just want to find the simplest path to doing the same thing we already have been, but compatible with a newer version SQL server. We have a lot of code dependent on LLBLGen, which would take unreasonable amounts of time to modify significantly.

I believe that I need a different template, which is why I'm posting here. If I'm misguided, please redirect me!

Using "Adapter" for the template, I generate the code, and then modify the "DALDBSpecific" and the "DAL" projects to have the newer LLBLGen DLLs. The DBSpecific project will then build. But, the DAL project doesn't. I get 2 build errors and 2 warnings.

Error    CS0246    The type or namespace name 'MyAccountEntity' could not be found (are you missing a using directive or an assembly reference?)    Steton.DataAccessLayer.Suite.DAL    D:\Workspaces\42\Steton\Stable\Main\Src\Data Access Layer\Suite\DAL\PersistenceManagers\PersistenceManagers.cs    14
Error    CS0246    The type or namespace name 'MyCFItemValueEntity' could not be found (are you missing a using directive or an assembly reference?)    Steton.DataAccessLayer.Suite.DAL    D:\Workspaces\42\Steton\Stable\Main\Src\Data Access Layer\Suite\DAL\DynamicObject\DynamicObjectManager.cs    635

Basically, the DynamicObjectManager isn't finding the My Entity class for the CFItem table, and PersistenceManagers isn't finding it for the Account table. Those were both in the EntitySubClasses folders before. I'm sure there are many other differences I'll need to track down, but this is where I am, for now.

I've only found guides for moving from 3.5 to 4.2 - is there one for what I'm trying to do?
Otis (LLBLGen Pro Team)   Posted on: 19-Nov-2015 11:04:09.
You're using adapter, not selfservicing, so selfservicing isn't going to work for you. Adapter had 2 different presets: the General and the TwoClassScenario. With the TwoClassScenario being the preset your code is using. We deprecated TwoClassScenario in 4.0, as it comes with a couple of problems, one being a tremendous amount of code is generated for not really a good reason and also awkward constructions of parallel hierarchies (Customer 1:n Order, and MyCustomer 1:n MyOrder, so a parallel hierarchy of Customer 1:n Order)

We still ship the preset though. In your installation folder, go to:Frameworks\LLBLGen Pro\Tasks\Deprecated

There you'll find the preset. Copy that file into Frameworks\LLBLGen Pro\Tasks, restart the designer and you should be able to see the preset.

I don't know what DynamicObjectManager or PersistenceManager are/do, they seem custom classes written by some developer at your company or a 3rd party consultant.

Now for the bad news: we did deprecate TwoClassScenario and it's not getting any updates. In v5 we'll drop it entirely and it won't come back. It was primarily created to have extension points to the generated code in the subclass for each entity, but in practice this turned out to be cumbersome and also redundant as there are partial classes now and we also added a CommonEntityBase class for all entities which, through partial classes, can be extended so the My* classes were no longer needed. As it was not really a great design to begin with, we dropped it also because we didn't see many people using it. (e.g. it had some bugs for a long time no-one reported)

I don't know how many code was added in your project to the 'My' classes. If that code is minor, you could do a global rename of the My*Entity usage to *Entity (using regexp replace in to make your code use the normal entity classes instead and migrate to the normal class model we generate. Then move the code which is added to the My* entity classes to partial classes of *Entity and you're set.

I'm sorry to hear you have these problems with our system. I hope the above info helps you get going. I also know that it's perhaps the easiest to just use the deprecated preset and move on, but I'd advise you to at least try to move the code to the normal adapter preset. But of course that might take more time so I don't know how much time you're given to accomplish this task.

If you run into more problems just let us know and we'll guide you through it.

jg (User)   Posted on: 19-Nov-2015 15:20:17.
Thanks for your reply. I will try the deprecated solution, for now. That seems like the fastest solution for the moment, and then I will talk to the team about the possibility of using the normal adapter for a more long term solution.
jg (User)   Posted on: 20-Nov-2015 21:00:14.
I've got it working with the deprecated presets. However, I wind up with errors that I have to fix manually, after generating the source code. I'm wondering if there's something I should change, to make the version built by LLBLGen work, without fixing it, each time.

The DatabaseSpecific project includes an Interface called IChangeHistoryTracking, and the partial "My" classes in the main DAL project don't include the ...DAL.DatabaseSpecific.Interfaces namespace, so I have to go in and add the using statement to 60+ classes that use that interface, along with adding the ...DAL.DynamicObject to quite a few of them. Can I edit the template for it, so it adds those?

Additionally, it created the DatabaseSpecific project and namespace as DALDBSpecific, and we want it as DAL.DatabaseSpecific - how do I make that happen?

Walaa (Support Team)   Posted on: 24-Nov-2015 00:05:01.
Please try to use the built in additional interface support.
jg (User)   Posted on: 29-Dec-2015 21:44:05.
We have run into some more problems with this upgrade, so I am testing out the idea of replacing our deprecated TwoClass template with the new default template and using partial classes, like you guys recommended. I don't know if that will fix our problems or not, but at least it might bring us closer inline with the recommended practice and make it easier to find answers to our questions.

The main problem I have run into with this transition is that we have a lot of code in the My*Entity classes that overrides and extends methods from the base class.

Something like this:


protected override List<IEntityCollection2> GetMemberEntityCollections()
    var baseList = base.GetMemberEntityCollections();
    return someCustomFunction(baseList);

I'm not really sure how to transition this code to the partial class paradigm. We obviously can't override the base method if there is now only 1 class. Is there any way to extend an individual method in a generated class? Or maybe to create a separate method that wraps the original method that could be called by LLBLGen instead of the original method? Or really any other ideas for how to approach this transition?

There is a huge amount of code in these custom extensions so a major refactor is probably not an option right now.

Otis (LLBLGen Pro Team)   Posted on: 30-Dec-2015 09:05:29.
What does 'someFunction' do in the case of your example?
jg (User)   Posted on: 30-Dec-2015 16:13:52.
We have hundreds of entities and they don't all do the same thing (which is why I generalized it to SomeFunction), but there are some things they have in common. The implementation is pretty complex because our entire UI framework depends on it (and the people who created this framework left he company years ago).

I don't want to get too bogged down in the details, but essentially we have some custom fields that we conditionally tie to our entities in the UI, but they aren't actually related in the DB and come from a separate table. So when an entity is edited we also need to check if the other custom fields were edited and save them when the first entity is saved.

In this example, SomeFunction actually takes the List<IEntityCollection2> that GetMemberEntityCollections returns and then does some conditional logic to possibly fetch some other entities and add them to the list. That new list is then returned and Save Entity actually handles saving all the related entities.

I know that probably sounds like we are trying to reinvent the wheel since you guys already provide recursive saving, but our use case is pretty strange so it kind of has to be that way.

Walaa (Support Team)   Posted on: 30-Dec-2015 18:58:49.
essentially we have some custom fields that we conditionally tie to our entities in the UI, but they aren't actually related in the DB and come from a separate table.

This sound like TargetPerEntity Inheritance hierarchy, doesn't it qualify to inheritance?
jg (User)   Posted on: 30-Dec-2015 19:20:02.
I don't believe that could work for us, but maybe I'm missing something.

Our use case:

We have many different clients running separate implementations of our code base and they only real difference is the data in the database. Everything in our product is data driven. So each client can have any number of different custom fields mapped to their entities and we don't know about those fields at compile time. At run-time we load the entity and all it's related custom fields based on our logic of how those entities are tied to those fields.

So for example, a single user record might have 0 custom fields Client A's website but 100 custom fields on Client B's website. Custom fields are rows in a table, so we can't know beforehand how many there are or what those fields would be.

The Entity Inheritance article you were referencing looks like you have to manage that in the designer, which isn't possible for us.

daelmo (Support Team)   Posted on: 30-Dec-2015 21:13:23.
What is the method you are actually overriding? Where do you call it?
Otis (LLBLGen Pro Team)   Posted on: 30-Dec-2015 22:15:34.
Additionally, I saw your collegue is also posting about this same issue on the forums. I found a different method to override for him, so I think that will help you in the mean time:

jg (User)   Posted on: 30-Dec-2015 23:02:16.
Great! Thank you! We'll look into that option of overriding the other method for now.

This is from your post in the other thread:
If you want to get rid of the deprecated templates, you have to make a small adjustment to the shipped normal templates where you change the generated method by appending a partial method call to it. After that you can then add the extra code to the partial method in a partial class.

That sounds like a very reasonable approach. Thank you for the suggestion. One question though, if we create a custom template, is that something that would potentially be broken anytime we upgraded LLBLGen in the future? With a change this small, it wouldn't be a big deal to create a new template every time we upgrade, but it would be something we'd have to remember to do each time.

Also, maybe this is an uncommon use case, but it seems like it could be useful for the base template to include some hooks like that in these methods. If the partial method isn't ever implemented, then it's removed at compile time anyway. Something to think about for future version.

Thanks again for your help!
Walaa (Support Team)   Posted on: 31-Dec-2015 16:49:08.
You might need to port your custom template when migrating to a major release.
Most importantly, copy the shipped templates, and edit the copied version rather than the original ones, create a templatebindings file with the same templateid binding but now referring to your own modified templates.