One Way Relationships with SelfServicing

Posts   
 
    
timbered
User
Posts: 48
Joined: 09-Feb-2020
# Posted on: 29-Mar-2020 22:07:08   

Hi!

Using 5.6.2, and SelfServicing.

I want to set up one-way relationships for my lookup tables (e.g. In a Customer entity, a navigator to a State in the States entity.)

I don't care about going from State -> Customer.

So I set up a one-way relationship (no Navigator from State to Customer.)

Now, I get a warning for the relationship that it "has one navigator which is empty, which could lead to problems with Selfservicing.)

So:

  1. What problems, and how should I avoid them?
  2. I'd need a really compelling reason to switch to Adapter at this point.
  3. Am I doing this incorrectly?
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 30-Mar-2020 08:01:05   

Hi timbered,

timbered wrote:

  1. What problems, and how should I avoid them?

It's only a problem for selfservicing, which requires the other side's navigator to be there for lazy loading. Customer.Orders 1:n Order.Customer. If Order.Customer is hidden/not there, to lazy load orders for a customer isn't possible as that's done by the Ordercollection, but as the order has no navigator on the relation ('Customer' isn't there), it doesn't know about Customer, hence it won't work. If you're using adapter instead, you have nothing to worry about in this regard. So, to fix it for SelfServicing, include both navigators. If you don't use lazy-loading on the other end (State->Customers) you shouldn't have problems.

timbered wrote:

  1. I'd need a really compelling reason to switch to Adapter at this point.

I don't think SelfServicing is a bad choice, however you have to consider the scenario. Personally I would prefer Adapter as I think it's easier to use it in all scenarios but no SelfServicing (Selfservicing is discouraged in distributed scenarios). (More about the topic on this thread).

timbered wrote:

  1. Am I doing this incorrectly?

It's a warning for Adapter (nothing to worry). However it's considered a potential runtime error for SelfServicing.

David Elizondo | LLBLGen Support Team
timbered
User
Posts: 48
Joined: 09-Feb-2020
# Posted on: 30-Mar-2020 11:40:07   

Thanks for the info.

Assuming I stay with Selfservicing:

So, in my example (one way from a Customer Address entity to State Abbreviations entity), will lazy loading will still work from Customer -> State? But I'll get a run-time error if I try to go State -> Customer. Correct? Or are you saying that even going from Customer -> State won't work?

I would put the navigators back in, but as I recall when I first had them, I got a warning about a circular reference - which I think was caused by the Customer having a Billing Address and a Shipping Address, both pointing to the State entity. State pointed back to two different FKs in Customer. That's what prompted me to remove them. Especially since I'll never have a need to go from my lookup tables to my Customer data anyway.

timbered
User
Posts: 48
Joined: 09-Feb-2020
# Posted on: 30-Mar-2020 14:11:02   

Thinking a bit more, it wouldn't even be possible to get from State -> Customer, since there's no navigator in State.

So I'm still confused as to why this is a problem with Selfservicing, and what scenario would cause the run-time error.

And for that matter, why isn't it a problem with Adapter?

So I'm obviously missing something.

This isn't a distributed app, nor am I using services, so that discussion you linked to doesn't really apply to me. I am SQL Server on a server box and client PCs with a fat app (where my entities are.)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39747
Joined: 17-Aug-2003
# Posted on: 30-Mar-2020 14:52:26   

It's a problem as the fetching is done 'on the other side' of the relationship. So if you trigger customer.Orders, the fetching is done in the Orders collection, using a pre-generated method based on all FK fields in Order. If the navigator on the FK side is hidden for Order, the navigation to Customer is hidden and it doesn't know how to fetch that as the generated method doesn't have support for it (as it's an unknown relationships from the Order's Point of view).

Hence the warning. In Adapter there's no fetching through a navigator, you specify the query and the destination like you'd normally do

In short, never hide navigators on the FK side. You might want to hide navigators on the PK side, but do that only in situations where you have to cache the PK side.

Adapter is highly recommended over selfservicing as it has more features and is more flexible. the only thing it doesn't have is lazy loading which is actually a feature you should avoid anyway.

Frans Bouma | Lead developer LLBLGen Pro
timbered
User
Posts: 48
Joined: 09-Feb-2020
# Posted on: 30-Mar-2020 15:19:29   

I'm trying it now with the generated code, and it seems to work. I read an address, and the State entity is there.

So, I'm even more confused now.

This isn't fetching a collection. As far as the database is designed, I have a FK inside my Address table that points to the key (a single key) of my States table. So, I can change / lookup (sorry, I'm in the USA and using that as an example) "CA" (address table) to "California" (State table).

My Address entity has a Ship To address and a Bill To Address. So, two state abbreviations. But each gets a single State entity, with the state name inside it.

All I want to do is have an Address entity, and find the State Name in the State table. State isn't a collection. Nor do I ever want to read a State and get a collection of Addresses.

That's is pretty basic RDBMS stuff, isn't it? Mind you, I'm new to ORM, but still.

Then how do I do this with Selfservicing? I don't think there's anything esoteric about what I'm trying to do, but it's quite possible part of my brain is still stuck at the non-ORM database table level and I'm not grasping a concept correctly.

And if it's not possible with Selfservicing, why would it then work with Adapter? What's the difference in this specific case that Adapter would work with no reference from State to Address?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39747
Joined: 17-Aug-2003
# Posted on: 30-Mar-2020 18:45:10   

timbered wrote:

I'm trying it now with the generated code, and it seems to work. I read an address, and the State entity is there.

So, I'm even more confused now.

This isn't fetching a collection. As far as the database is designed, I have a FK inside my Address table that points to the key (a single key) of my States table. So, I can change / lookup (sorry, I'm in the USA and using that as an example) "CA" (address table) to "California" (State table).

My Address entity has a Ship To address and a Bill To Address. So, two state abbreviations. But each gets a single State entity, with the state name inside it.

All I want to do is have an Address entity, and find the State Name in the State table. State isn't a collection. Nor do I ever want to read a State and get a collection of Addresses.

That's is pretty basic RDBMS stuff, isn't it? Mind you, I'm new to ORM, but still.

Yes, and this is OK. The lazy loading from FK to PK is fine, as it uses a lambda using the PK fetch.

So in Address you have an FK to state which is the PK side of the relationship, and the lazy loading for the state entity from the address entity will use e=>e.FetchUsingPK(statePk) where 'e' is the state entity class instance. So that's ok.

If you want to go the other way around, it's not ok. You don't need that, that's fine, but fetching the 'many' side of the relationship fails. The warning is there to let you know that that can happen. You won't run into the side effect as you're not planning to go from state to address, so you can decide to hide the warning if you want. It won't affect your code. That's also why it's a warning: things could go wrong in your code if you want to use the pk -> fk side of the relationship in a lazy loading scenario and you should be aware of that hence the warning and not an error, as things will work fine from the other side of the relationship.

Then how do I do this with Selfservicing? I don't think there's anything esoteric about what I'm trying to do, but it's quite possible part of my brain is still stuck at the non-ORM database table level and I'm not grasping a concept correctly.

And if it's not possible with Selfservicing, why would it then work with Adapter? What's the difference in this specific case that Adapter would work with no reference from State to Address?

What you're doing is perfectly fine, the warning is there to let you know that if you hide one navigator it might be you run into a problem with selfservicing's lazy loading code. You can always fetch data even if there are no navigators, e.g. through linq or queryspec or using the low level API where you new up a collection instance and use GetMulti().

So in short: don't worry about it simple_smile

Frans Bouma | Lead developer LLBLGen Pro
timbered
User
Posts: 48
Joined: 09-Feb-2020
# Posted on: 30-Mar-2020 19:02:08   

It being a warning goes back to my original question, in that I know I can't go in two directions if I have only one navigator. I just wanted to make sure something else wasn't going on that I would find out the hard way down the road.

And, as to your last point, because of a completely separate design decision, I'm considering doing away with the navigators on my lookup tables and doing it in code anyway.

But, thanks so much to both of you for the help. This is my first real project using Llblgen, and it's been a tremendous asset. So, no regrets. I just have to learn the ins and outs.