1) about EntitySet<T>.ListChanged, I've tried to implement it's behaviour
coping it's behaviour from linq to sql. It actually have strange behaviour,
but somewhere I've added tests for that... Let me know if you have found
some inconsistence.

2) about the cache, it could take a while to proper fix the problem: if
parameters value are cached, probably we should not simply change the cache
implementation, but it's interface too. And probably the place where it's
filled and the way it's looked up.

3) may be the MemberModificationHandler need some refactoring too. But int
the example you provide, the first SubmitChanges should save a copy of the
original entity state, allowing to check when something chages.
That's probably the reason for which the SubmitChanges Register() submited
entities.

I really hope to find the time to fix this issue today.
The cache problem could be far more complex. A fast way could be to go back
to the old ExpressionEqualityComparer, but in many case (almost all our) it
would make the cache too big in memory and with very few cache hit.



@Pascal: sometime ago, you said that the SQL builder handle query parameters
in a particular way to handle dbrms that does not support named parameter.
Could we use this to cache the evaluated expression without the actual
values of parameters?



Giacomo


On Mon, May 11, 2009 at 7:10 AM, Jonathan Pryor <[email protected]> wrote:

>  After more debugging, I'm heading to bed, but this is what I've found out:
> our change tracking isn't tracking changes. :-)
>
> Specifically, when you have code like this (using something NUnit-testable
> instead of from NerdDinner):
>
> Category c = GetExistingCategory();
> Product p = new Product {...};
> c.Products.Add(p);
> db.SubmitChanges();
>
>  the newly added product isn't actually added to the database.  The problem
> *appears* to be because of MemberModificationHandler: it only tracks
> INotifyPropertyChanged and not INotifyPropertyChanging (see
> MemberModificationHandler.RegisterNotification()).
>
> So, what happens is c is a tracked object (yay).  As such, it is
> registered with the EntityTracker (double yay).  However, for change
> tracking to work, MemberModificationHandler uses the
> INotifyPropertyChanged interface.  In this case, c.Products.Add(p) doesn't
> actually invoke MemberModificationHandler.OnPropertyChangedEvent(),
> because it isn't registered.
>
> Specifically, the registered Category fires the
> INotifyPropertyChanging.PropertyChanging event, because (as far as it
> knows) c.Products will be changing.  However, c doesn't know what, if
> anything, will change.  c.Products.Add(p) eventually calls into
> Category.attach_Products(), which then effectively does 'p.Category = c'.
> This last expression is what fires the
> INotifyPropertyChanged.PropertyChanged event, but only on p, which hasn't
> been registered with *anything*, and thus there are no handlers
> registered.
>
> Oops.
>
> The only solution I can think of is that MemberModificationHandler needs
> to listen to the INotifyPropertyChanging.PropertyChanging event (if
> available), and if it's fired it needs to check for changes on 
> *all*properties of the changing object.
>
> So I did this, and it still fails (see attached patch, which includes the
> unit test).  It properly detects that 'c' may have changed, but
> QueryRunner.Update() doesn't do a "deep" update; that is, it only updates
> the Category properties (CategoryName, Description, etc.) but not the
> values of anything attached to it (like the Category.Products collection).
>
> Any ideas on how to resolve this?
>
> Thanks,
> - Jon
>
>
> On Sun, 2009-05-10 at 22:02 -0400, Jonathan Pryor wrote:
>
> I already fixed this, and it has been committed to svn.
> DataContext.SetEntitySetQueries() was being called because of
> DataContext._GetOrRegisterEntity(), which in turn was called by
> DataContext.Register(), which was called by DataContext.SubmitChanges().
> (Just check the callstack in the original message...)  The problem was
> twofold:  (1) DbLinq's EntitySet<T> was screwy (though I blame a lot of
> that screwiness on .NET's EntitySet<T> -- see the new EntitySetTest.csfile, 
> and laugh hysterically when you see
> *when* the EntitySet<T>.ListChanged event is raised), and (2) calling
> dinner.RSVPs.Add(rsvp) caused the EntitySet<RSVP> source to be created,
> and EntitySet<T>.SetSource() cannot be called again once
> EntitySet<T>.HasLoadedOrAssignedValues is true.  Since
> DataContext.SetEntitySetsQueries() tried to do just that, it threw an
> exception.
>
> Now I'm working on a related bug: subsequent updates aren't tracked.  To
> wit:
>
> Dinner dinner = new Dinner {...};
> RSVP rsvp = new RSVP();
> rsvp.AttendeeName = User.Identity.Name;
> dinner.RSVPs.Add(rsvp);
> db.Dinners.InsertOnSubmit(dinner);
> db.SubmitChanges();
>
> // The above now works.  Now...
>
> RSVP rsvp2 = new RSVP();
> rsvp2.AttendeeName = "whatever";
> dinner.RSVPs.Add(rsvp2);
> db.SubmitChanges();
> // rsvp2 is NOT submitted to the database.
>
>  I'm still tracking down why this happens.  The attached patch file
> recreates this same scenario within the unit tests, and also (thankfully)
> fails.
>
> What I would appreciate is if you could look into the cache issues that I'm
> seeing. :-)
>
> Thanks,
> - Jon
>
> On Sun, 2009-05-10 at 23:41 +0100, Giacomo Tesio wrote:
>
> I think this is due to the "dinner.RSVPs.Add(rsvp);"  line where you
> actually fill the EntitySet.
>
> The DataContext.SetEntitySetQueries() should not run on just inserted
> entity, since they are yet filled.
>
>
> Tomorrow I'll try to fix this...
>
>
> Giacomo
>
>
> On Fri, May 8, 2009 at 4:59 AM, Jonathan Pryor <[email protected]> wrote:
>
> Still continuing with my "NerdDinner on Mono" effort, and hitting the
> following issue:
>
> When I attempt to add a new Dinner, NerdDinner effectively does:
>
> Dinner dinner = new Dinner {...};
> RSVP rsvp = new RSVP();
> rsvp.AttendeeName = User.Identity.Name;
> dinner.RSVPs.Add(rsvp);
> db.Dinners.InsertOnSubmit(dinner);
> db.SubmitChanges();
>
>  This fails, with:
>
> System.Reflection.TargetInvocationException: Exception has been thrown by the 
> target of an invocation. ---> System.InvalidOperationException: The EntitySet 
> is already loaded and the source cannot be changed.
>   at System.Data.Linq.EntitySet`1[NerdDinner.Models.RSVP].SetSource 
> (IEnumerable`1 entitySource) [0x00000]
>   at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke 
> (object,object[],System.Exception&)
>   at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags 
> invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, 
> System.Globalization.CultureInfo culture) [0x000ca] in 
> /home/jon/Development/mono-HEAD/mcs/class/corlib/System.Reflection/MonoMethod.cs:169
>   --- End of inner exception stack trace ---
>   at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags 
> invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, 
> System.Globalization.CultureInfo culture) [0x000e5] in 
> /home/jon/Development/mono-HEAD/mcs/class/corlib/System.Reflection/MonoMethod.cs:179
>   at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] 
> parameters) [0x00000] in 
> /home/jon/Development/mono-HEAD/mcs/class/corlib/System.Reflection/MethodBase.cs:111
>   at System.Data.Linq.DataContext.SetEntitySetsQueries (System.Object entity) 
> [0x00173] in 
> /home/jon/Development/mono-HEAD/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/DataContext.cs:608
>   at System.Data.Linq.DataContext._GetOrRegisterEntity (System.Object entity) 
> [0x00015] in 
> /home/jon/Development/mono-HEAD/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/DataContext.cs:468
>   at System.Data.Linq.DataContext.Register (System.Object entity) [0x0000d] 
> in 
> /home/jon/Development/mono-HEAD/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/DataContext.cs:675
>   at System.Data.Linq.DataContext.SubmitChanges (ConflictMode failureMode) 
> [0x000a6] in 
> /home/jon/Development/mono-HEAD/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/DataContext.cs:378
>   at System.Data.Linq.DataContext.SubmitChanges () [0x00000] in 
> /home/jon/Development/mono-HEAD/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/DataContext.cs:339
>   at NerdDinner.Models.DinnerRepository.Save () [0x00000]
>   at NerdDinner.Controllers.DinnersController.Create 
> (NerdDinner.Models.Dinner dinner) [0x00000]
>
>  Suffice it to say, this doesn't happen under .NET's System.Data.Linq.  I'm
> wondering if anyone has seen a similar error to this before, and/or knows
> what an appropriate fix would be.
>
> Thanks,
> - Jon
>
>
>
>
>
>
>
>
>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"DbLinq" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/dblinq?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to