Migrating from SelfServicing to Adaptor

Posts   
 
    
hostileant
User
Posts: 9
Joined: 14-Feb-2017
# Posted on: 14-Feb-2017 06:40:19   

Hi Everyone,

Is there any documentation or recommended process for migrating a large application from Self Servicing to Adaptor?

Is it possible to set the designer to generate both self servicing and adaptor in the generation process with different namespace so I can progressively migrate? Should I just churn through it?

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 14-Feb-2017 17:06:14   

It's a matter of converting query code one by one. If you use linq/queryspec, the changes are not that big (for linq, you use a different LinqMetaData constructor). If you use the low-level API, a lot of code will be required to be changed: e.g. FieldCompareValuepredicate for adapter has a different constructor.

Always work in a separate codebase: generate the adapter code in a different folder. Then reference the two adapter projects in your own code and remove the reference to the selfservicing project. Then compile and you'll get a massive amount of errors, so correct them one by one.

you have to migrate cold-turkey, you can't keep both in the code, as it won't work in general at runtime.

It depends on the amount of code of course, but you'll quickly pick up the differences and migrating code will be straight forward.

The last step will be to fix issues related to lazy loading: code which currently depends on lazy loading will now no longer work and you have to refactor your code to use eager loading up front. (prefetch paths).

Optionally, after things work again!, is to refactor your code a bit so you can reference the dbspecific project from adapter only in the parts where you use the database, and reference the dbgeneric project (with the entities) in parts where you don't use the database.

Just out of curiosity, why switch to adapter?

Frans Bouma | Lead developer LLBLGen Pro
hostileant
User
Posts: 9
Joined: 14-Feb-2017
# Posted on: 15-Feb-2017 05:42:45   

Otis wrote:

Just out of curiosity, why switch to adapter?

I started using LBLLGen when v2 was just launched and chose self servicing and never had a good enough reason to change but a lot has changed since v2 in relation to not just LLBLGen but also the number of platforms and apps we need to support.

Primarily we'd like to move our main winforms application (nearly 200 tables, over 100 forms in the project) from communicating directly with the database to a web services based model since our business seems to be becoming geographically more distributed every year plus so we can lock the database down more. I've used adapter in a couple of other smaller projects and have been pretty happy with how everything serializes and performs.

Additionally there are a few quirks with LLBLGen and DevExpress that have never caused enough of an issue on their own to cause me to change but they're definitely there.

In particular two issues with the XtraGrid.

  1. When you use the Master->Detail Grid even if you explicitly define the relations you want to have detail tabs for it still crawls all the relations on an entity in certain events. This causes the lazy loading to pull every record for every relation from the database. DevExpress can't stop that crawl and I don't believe LLBLGen can stop the lazy loading for a single collection object. Not a show stopper but for entities with a large number of relations it can cause noticable delays in the gui client.

  2. Sometimes when binding a collection object to (once again) a Master->Detail grid it will delete from the database all the entities in the collection. This is intermittent and I've had this particular problem in two completely different projects which would lead me to believe there is a bug there but extremely difficult to reproduce.

The solution to both is to not bind collections to master->detail grids and use alternatives (poco lists, datatable etc) which is OK but really the issue here is that the nature of SelfServicing is that you surrender control over when, how and why the database is accessed.

Self Servicing also doesn't encourage efficient use of the database, I've seen plenty of code by various developers where a whole entity will be fetched just to access one piece of information from a related entity. On a small entity that is fine but bigger ones or nesting 2 - 3 levels deep it is inefficient but easy to do.

Really, I've lived in regret of choosing Self Servicing many years ago and the time has come to right my wrongs even though it is going to be some tough work. A lot of our core code was written back before queryspec and is using the low level api. Additionally, habit of using the low level api meant we didnt commence using queryspec until well after it's release.

Given the size of the job ahead of us I investigated changing ORM altogether or using T4 with a micro orm but to be honest LLBLGen comes out on top every time. The latest 5.1 feature for Plain SQL API will remove a whole class we wrote for doing that job and remove the need for dapper in our project too.

My only real wish for the designer would be the typed list editor to have a better visibility for which relation is being used. For instance if we have an Invoice table it might have 3 or 4 relations to the employee table (who created it, who was the sales person, who shipped it etc) but because we are database first we end up with the relations called Employee, Employee, Employee, Employee__ etc. Since we've never got around to naming them all with proper names in LLBLGen it makes the Typed List editor very awkward to use. If the field names that the relations represented were displayed (or the relation names were based on the fields joined instead of table plus an underscore) then it would make me hate creating typed lists less!

Keep up the great product.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Feb-2017 11:06:35   

hostileant wrote:

Otis wrote:

Just out of curiosity, why switch to adapter?

I started using LBLLGen when v2 was just launched and chose self servicing and never had a good enough reason to change but a lot has changed since v2 in relation to not just LLBLGen but also the number of platforms and apps we need to support.

Primarily we'd like to move our main winforms application (nearly 200 tables, over 100 forms in the project) from communicating directly with the database to a web services based model since our business seems to be becoming geographically more distributed every year plus so we can lock the database down more. I've used adapter in a couple of other smaller projects and have been pretty happy with how everything serializes and performs.

That setup is indeed better off with adapter: you can then use the dbgeneric project in the UI, and keep the dbspecific project on the server side.

Additionally there are a few quirks with LLBLGen and DevExpress that have never caused enough of an issue on their own to cause me to change but they're definitely there.

In particular two issues with the XtraGrid.

  1. When you use the Master->Detail Grid even if you explicitly define the relations you want to have detail tabs for it still crawls all the relations on an entity in certain events. This causes the lazy loading to pull every record for every relation from the database. DevExpress can't stop that crawl and I don't believe LLBLGen can stop the lazy loading for a single collection object. Not a show stopper but for entities with a large number of relations it can cause noticable delays in the gui client.

Yes, this is a typical SELECT N+1 problem caused by lazy loading. If the property is in the grid, then it will be read. You have a field-mapped-onto-related-field in the entity (which will trigger lazy loading), or you have the property mapped onto the relation in the grid? Lazy loading can be switched off by setting "AlreadyFetched<propertyName>" but that's on an individual entity instance. An entity collection is bound through its EntityView instance which implements ITypedList (the .net interface) which avoids reflection from the grid, so it should not trigger lazy loading for properties that aren't bound in the grid.

  1. Sometimes when binding a collection object to (once again) a Master->Detail grid it will delete from the database all the entities in the collection. This is intermittent and I've had this particular problem in two completely different projects which would lead me to believe there is a bug there but extremely difficult to reproduce.

Hmm, this is quite serious. I haven't seen any report about this, but if you can find out what causes it, we really want to know. The runtime has always had the policy that an entity removed from the collection isn't deleted from the database, so it's especially odd that it happens here.

The solution to both is to not bind collections to master->detail grids and use alternatives (poco lists, datatable etc) which is OK but really the issue here is that the nature of SelfServicing is that you surrender control over when, how and why the database is accessed.

Yes, it's an all or nothing approach. We start to promote adapter more over selfservicing so new users will use it over selfservicing, as for small projects it's 'ok', but for larger projects adapter is the more flexible choice. It's a shame adapter was designed after selfservicing, as selfservicing should have been a wrapper around adapter so we would have had 1 code base and not one with a split personality wink It also would have been better for users as they would simply ditch the wrapper and they would be on adapter. But backwards compatibility has always kept them separate. We have refactored a lot of code to be shared among them now, so they're both thin layers around the same core, but to the outside it's not that easy to switch from one to the other.

Self Servicing also doesn't encourage efficient use of the database, I've seen plenty of code by various developers where a whole entity will be fetched just to access one piece of information from a related entity. On a small entity that is fine but bigger ones or nesting 2 - 3 levels deep it is inefficient but easy to do.

Yeah lazy loading is a terrible thing after a while: it's so easy to simply traverse the graph and obtain some data, but under the hood it's not good at all.

Really, I've lived in regret of choosing Self Servicing many years ago and the time has come to right my wrongs even though it is going to be some tough work. A lot of our core code was written back before queryspec and is using the low level api. Additionally, habit of using the low level api meant we didnt commence using queryspec until well after it's release.

sorry to hear using our work caused this much trouble. I hope the transition to adapter is smooth. To help in your confidence: I ported this forum's code from selfservicing to adapter in a couple of days. It is fairly straightforward. With the lowlevel api, if you use the operator overloads, e.g. CustomerFields.CompanyName=="Foo Inc", it's the same on adapter.

With transitions like this, it's key not to fall into the trap to refactor the code at the same time! It's so tempting to update it at the same time to a better piece of code using newer APIs. Don't do that, as you'll end up with a project that will last way longer than expected: first migrate to adapter, then refactor.

If you have specific questions regarding porting to adapter, just ask simple_smile If you're fluent with regular expressions, you can try to convert patterns you use a lot to adapter with a global search/replace in vs.

Given the size of the job ahead of us I investigated changing ORM altogether or using T4 with a micro orm but to be honest LLBLGen comes out on top every time. The latest 5.1 feature for Plain SQL API will remove a whole class we wrote for doing that job and remove the need for dapper in our project too.

simple_smile

My only real wish for the designer would be the typed list editor to have a better visibility for which relation is being used. For instance if we have an Invoice table it might have 3 or 4 relations to the employee table (who created it, who was the sales person, who shipped it etc) but because we are database first we end up with the relations called Employee, Employee, Employee, Employee__ etc. Since we've never got around to naming them all with proper names in LLBLGen it makes the Typed List editor very awkward to use. If the field names that the relations represented were displayed (or the relation names were based on the fields joined instead of table plus an underscore) then it would make me hate creating typed lists less!

In v5.1, load your project, go into the project settings, click on Entity Model -> Element Name Construction -> General, then change the patterns on the right side for Navigator Mapped onto .... (there are 3). You can include e.g. the start entity field names using a macro (click a setting to see the help on these). Once you're done, simply click OK, and the designer will update all names based on your new pattern. simple_smile No more ___ suffixes and no more manual rename every single one of them simple_smile reverse engineering new relationships also automatically pick up the new pattern for the names.

Of course code using the _____ suffixes now will break, so apply this with care, but I hope this will make things less tedious simple_smile

Keep up the great product.

Thanks! We will simple_smile

Frans Bouma | Lead developer LLBLGen Pro