empty navigator field

Posts   
1  /  2
 
    
Posts: 34
Joined: 11-Apr-2011
# Posted on: 11-Apr-2011 12:42:26   

Hello,

I'm using version 3.1 of llbl and I'm trying to generate code for .Net 4.0 Entity Framework with self tracking.

I have 1 : many relationship between User and Country tables. Country is a PK side and should not know about User. So the Navigator field is empty. However generated code seems to be wrong and not compile.

It still create viarable for missing navigator and it looks like this:

TrackableCollection<User> _;

The methods to clear or fixup navigator are also wrong:

protected override void ClearNavigationProperties() { this..Clear(); base.ClearNavigationProperties(); }

private void FixupCountry(CountrypreviousValue, bool skipKeys) { if(this.IsDeserializing) { return; } if(previousValue != null) { previousValue..Remove(this); } if(Country != null) { Country..Add(this); } this.ChangeTracker.FixupSingleEntity(this.Country, previousValue, "Country"); } How to fix it?

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 11-Apr-2011 16:14:09   

Your question is not clear enough.

  • I guess you mean SelfServicing, by Self tracking, right?
  • Did you remove the User navigator inside the Country Entity? What kind of compilation errors do you get?
Posts: 34
Joined: 11-Apr-2011
# Posted on: 12-Apr-2011 10:58:25   

Not self servicing. Self tracking - preset Self Tracking POCO entities. I removed User navigator field. The compilation error is because of syntax errors. See code samples in original post.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 12-Apr-2011 11:07:57   

I see. Do you mean the double dots ".."?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 12-Apr-2011 12:59:01   

We've to verify whether an optional navigator is supported by STE's and if so, we'll fix the template. Till then, keep the navigator around (i.e. have both navigators in the relationship).

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 11-Apr-2011
# Posted on: 12-Apr-2011 13:54:33   

Yep, I mean double dots. It looks like template still generates code for empty navigator.

So far I've commented all wrong lines and it seems to work properly.

Waiting for feedback. Thx.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 12-Apr-2011 14:58:25   

Looks like a bug in the template. However, I can't say if the selftracking entities still work if you remove a navigator (it should, but we ported the MS code over, so it might be they didn't think of this and the original template might have an issue with this).

The steEntityClass.lpt template contains a couple of issues. It does filter out optional navigators for the property generation, but the rest should be done properly as well. We'll fix the template and will attach the fixed template to a new post in this thread.

(edit) POCO templates have the same problem.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 12-Apr-2011 16:29:03   

Please copy the attached template into the folder: <llblgen pro installation folder>\Frameworks\Entity Framework\Templates\V4\C#

Do this as Administrator, overwriting the existing one.

There's still a problem with removing the navigator on the FK side and STEs (fixup doesn't work in some edge cases), but as that doesn't really make any sense, it's not really an issue for now: the fk fields aren't present in some cases (as they're optional) and they can't be set to a value anyway, as the FK side doesn't know about the PK side in this case.

Your situation is different, you removed the PK side's navigator.

Attachments
Filename File size Added on Approval
steEntityClass.lpt 23,103 12-Apr-2011 16:29.12 Approved
Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 11-Apr-2011
# Posted on: 13-Apr-2011 09:46:26   

It works.

Thank you.

Posts: 34
Joined: 11-Apr-2011
# Posted on: 06-May-2011 12:06:08   

Hello again,

You fixed the template and code is compiling. However I think too many code is removed. Right now the whole FixupNavigator body is empty and the information about changes in children objects is lost.

Please consider changes like this:

this.FixupNavigator<T>(e.NewItems, e.OldItems, null, "NavigatorName",null, false);

and in CommonEntityBase :

... if(assignmentFunc != null) assignmentFunc(this, item); ... if (equalityComparerFunc != null && assignmentFunc != null) { if (equalityComparerFunc(this, item)) { assignmentFunc(null, item); } }

Antyradary
User
Posts: 1
Joined: 07-May-2011
# Posted on: 07-May-2011 14:14:43   

I put the attached template into the folder as Otis wrote into: <llblgen pro installation folder>\Frameworks\Entity Framework\Templates\V4\C#

Now is ok, thanks simple_smile

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 08-May-2011 18:29:52   

leszeks1313 wrote:

You fixed the template and code is compiling. However I think too many code is removed. Right now the whole FixupNavigator body is empty and the information about changes in children objects is lost.

What do you mean by "changes in children objects are lost"? Please elaborate more.

David Elizondo | LLBLGen Support Team
Posts: 34
Joined: 11-Apr-2011
# Posted on: 12-May-2011 12:40:06   

In self tracking each entity has object ChangeTracker where all information about changes are stored. You always know which property has been changed, objects added or removed from/into children collection. Hovewer this works only when code in FixupNavigator is not empty. In fixed template body of FixupNavigator is empty so the changes are not tracked.

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 12-May-2011 20:58:38   

That's slightly odd - the template for CommonEntityBase has no functionality in there to generate an empty FixUpNavigator function, in fact it's a completly static template as it is just duplicating what VS would generate for that class. I'm slightly puzzled as to why yours would end up empty.

Please could you sends us you generated CommonEntityBase.cs and the steCommonEntityBaseClass.lpt template file that it's generated from and we'll take a look.

Thanks

Matt

Posts: 34
Joined: 11-Apr-2011
# Posted on: 19-May-2011 09:23:27   

Template and CommonEntityBase class is not changed. Changed is only template for ste entity. It is attached to this thread. FixupNavigator is in this template and the whole body is empty if navigator is not filled. I'd like to change this template that changed would be tracked even if navigator field is empty. To do that changes in both templates are needed. See code example in above post.

Thanks

Leszek

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 19-May-2011 11:38:55   

I'm confused. I need an example of a couple of entities with an empty navigator the way you use it. The reason I ask is that I have the suspicion you want to track changes on the FK side when the FK side navigator is missing. This is not really possible, semantically speaking, as the FK side is the one which actually initiates the relationship. I.o.w.: if the navigator isn't there on the FK side, there is technically not a relationship. Example: if I have Customer.Orders 1:n Order.Customer, and I remove 'Order.Customer', from the point of view of 'Order' there's no relationship with Customer, as there's no way to tie an order to a customer as it can't set an FK field under the hood in the target table.

I also want to know what exactly you want to 'track' with respect to the related entity on the side where the navigator is missing (as I understand it) as there's no navigator, so that side doesn't know there is a related entity.

The way we fixed the template was: we built the same relationship as you described earlier in EF, generated STE code from that and ported that to our own templates. We use different code (as we re-use a base class method, to avoid code bloat) To our knowledge our change does exactly what vanilla EF templates do too in this case. Hence my confusion wink

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 11-Apr-2011
# Posted on: 23-May-2011 10:05:44   

See the example below: I have 2 entities Incident and Persons, where relationship is 1:n. I'd like to have navigator field in incident "Persons" and track changes in this collection. On the other side Person should not know about Incident:

Where navigator is on both side I have in Incident entity class:

private void FixupPersons(object sender, NotifyCollectionChangedEventArgs e) { this.FixupNavigator<Person>(e.NewItems, e.OldItems, (v, i) => i.Incident=(Incident)v, "Persons", (v, i) => ReferenceEquals(i.Incident, v), false); }

if there is only one navigator the code is:

private void FixupPersons(object sender, NotifyCollectionChangedEventArgs e) { }

I'd like to have :

private void FixupPersons(object sender, NotifyCollectionChangedEventArgs e) { this.FixupNavigator<Person>(e.NewItems, e.OldItems, null, "Persons", null, false); }

This allows to track changes but not set navigator on the side where it not should. The change like that requires also modyfication of CommonEntityBase template described in above post.

I hope it is cleaner now simple_smile

Thanks, Leszek

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 23-May-2011 12:50:14   

Not having a navigator in Persons means the FK side doesn't know about the PK side, which is exactly what I meant: the relationship actually isn't there.

Without a navigator, there's not really something to fix up for that navigator. Don't you want it the other way around? No navigator in Incident but you do want one in Person? That would make more sense: the relationship is Incident 1:n Person, and therefore 'Person' needs to know it is related to Incident, otherwise you can't save an Incident - Person relationship to the DB, as there's no FK field in the table.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 11-Apr-2011
# Posted on: 24-May-2011 16:11:04   

I want navigator in Incident but don't want in Person. So Person does not know about incident but incident has collection of Persons. In my case I never save Person object. It's saving always with incident.

Please take a look on attached code. In this situation Navigator exists on PK side but code to fixup this navigator does not exist.

private void FixupPersons(object sender, NotifyCollectionChangedEventArgs e) { }

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 25-May-2011 13:53:20   

leszeks1313 wrote:

I want navigator in Incident but don't want in Person. So Person does not know about incident but incident has collection of Persons. In my case I never save Person object. It's saving always with incident.

I can understand this setup, but I don't understand why you want change tracking on the 'Person' side, as 'Person' has no clue what an Incident is, so there is nothing to track. Saving Incident AND Person won't insert anything into person related to Incident (EF fails in this, correctly).

What I also wonder is, how would EF know which person is related to which incident if there's no info in Person tying it to incident? Or did you map FK fields (which IMHO don't work in this case in EF).

Please take a look on attached code. In this situation Navigator exists on PK side but code to fixup this navigator does not exist. private void FixupPersons(object sender, NotifyCollectionChangedEventArgs e) { }

There's nothing attached, did you forget to attach a file? (can happen, you have to click the 'upload button')

Leszek, could you create a small llblgen pro project (with incident and person, exactly the way you want it to be), with db schema and also a small EF project directly made with the same schema so we can check whether it is indeed a bug or something EF can't deal with. We wrote the STE templates after MS' code, and their code doesn't fixup anything with a missing navigator on the FK side (which is logical, there's nothing to fixup, and it can't persist anything for 'Person'). I have the feeling we think you want to do more things than you really want to, so this repro project is essential.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 11-Apr-2011
# Posted on: 26-May-2011 14:37:32   

OK,

Attached is sample llbl project with generated code. I added comments to CommonEntityBase and Incident ( FixupNavigator).

Attachments
Filename File size Added on Approval
llbl.zip 30,823 26-May-2011 14:37.50 Approved
MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 26-May-2011 21:46:25   

Thanks for that - we'll investigate and let you know.

Matt

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 31-May-2011 12:02:27   

Looking into it. I have to say up front: It's likely that we don't add this, for the following reasons: 1) Microsoft doesn't generate the fixup code for this particular setup as well 2) It makes no sense, logically, because Person has no knowledge of Incident, therefore the fixup logic, even if it was implemented, has no meaning: what should be happening in the database?

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 31-May-2011 13:55:31   

I see your additions, however they have no effect: the problem is that there's no relationship FROM person TO incident. This means that even if the code you added is called, it won't have any effect, or better: it can't have any effect, as there's no relationship FROM person TO incident, meaning person has no knowledge of incident. That's also why Microsoft doesn't generate them and also why we don't generate them: removing a person from the Persons collection doesn't need tracking because it won't need any saving on the person side: person doesn't know anything about incident.

I hope you understand my explanations, and do realize why this is the way it is. simple_smile If not, please think about what needs to happen IF the fixup is done and you persist an incident. What should be done in the database? Updating a person? Can't be done, person has no knowledge of incident, so no fk field.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 11-Apr-2011
# Posted on: 01-Jun-2011 15:44:18   

I understand your explanation but I disagree that you need this relationship on both sides. The effect is in tracking collections. Person has no knowledge of incident but Incident know about changes. If you want to remove Person you can do it from Incident side and I'd like to see in Incident.ChangeTracker.ObjectsRemovedFromCollectionProperties that change.

1  /  2