Can I control depth of save?

Mar 12, 2011 at 11:46 PM
Edited Mar 12, 2011 at 11:46 PM

I have an object with a list of children, the children numbering possibly into the thousands and holding quite a bit of data each.  If some property of the parent object is changed, is there any way to tell Sterling to persist only the parent object and not its children?  Thanks!

Coordinator
Mar 13, 2011 at 3:11 PM

Yes. With the latest drop (not the 1.0 release, but the most recent changeset) you can set a predicate to define what makes an instance "dirty." So in your case, you might have a flag on the child elements or some other mechanism. When you define the table, you'd add the .WithDirtyFlag<MyClass,int>(obj=>obj.IsDirty) or similar. If the dirty flag is not set, the save will just write the foreign key for the parent object and not persist the child object. I'll be working on more documentation and examples for that.

Mar 13, 2011 at 5:45 PM

Got it. 

It'll do, but this isn't my favorite way to accomplish this, because I will end up littering my model objects with logic thats pertinent only to persistence.  I favor the approach taken by JDO in the Java world, where, via attributes, you give names to fields that are to be persisted.  Then, when you persist, you use the names to specify which of the fields to include.  This way, persistence logic stays where it belongs, in the persistence layer:  It works roughly as follows:

class Parent{

[ToPersist Name="ChildrenCollection"]

List<Child> Children;

}

So, to save just the parent, you would do: .Save(InstanceOfParent, null);

To save the parent with the children, you would do: .Save(InstanceOfParent, new List<string>(){ "ChildrenCollection" }); 

Mar 15, 2011 at 12:23 AM
Edited Mar 15, 2011 at 3:33 AM

I'm attempting to implement the WithDirtyFlag as follows:

public predicate in base model class named StateObject: 

public Predicate<StateObject> IsDirty = (StateObject obj) => false;//{ return (obj.State == State.Added || obj.State == State.Modified || obj.State == State.Deleted); };

 

Table definition: 

 

 CreateTableDefinition<Category, Guid>(c => c.ID)
                                .WithIndex<Category, Guid, Guid>(idxCustomerID, t => t.CustomerID)
                                .WithDirtyFlag<Category,Guid>(o=>o.IsDirty(o))

 

 

When I run my Windows Phone application I receive the following error message in Extensions.WithDirtyFlag (Extensions.cs line 56).

System.InvalidCastException was unhandled  Message=InvalidCastException  StackTrace:       at Wintellect.Sterling.Database.Extensions.WithDirtyFlag[T,TKey](ITableDefinition table, Predicate`1 isDirty)       at BTT.PinPointTime.WinPhone.Database.DatabaseInstance._RegisterTables()       at Wintellect.Sterling.Database.BaseDatabaseInstance.PublishTables()       at Wintellect.Sterling.Database.SterlingDatabase.RegisterDatabase[T]()       at BTT.PinPointTime.WinPhone.App.ActivateEngine()       at BTT.PinPointTime.WinPhone.App.StartupInitialization()       at BTT.PinPointTime.WinPhone.App.Application_Launching(Object sender, LaunchingEventArgs e)       at Microsoft.Phone.Shell.PhoneApplicationService.FireLaunching()       at Microsoft.Phone.Execution.NativeEmInterop.FireOnLaunching()

Do I have something wrong in my implementation of this functionality?

Mar 15, 2011 at 3:54 AM

I worked out what was going wrong here - I had doubled up on a WithDirtyFlag in one of my table definitions.

Mar 15, 2011 at 6:03 AM

OK working through this a bit further I now find that after saving data (retrieved from WCF service) when I later try to load that data I get the following error (at line 418 of SerializationHelpers.cs):

System.MissingMethodException was unhandled  Message=MissingMethodException  StackTrace:       at System.Activator.InternalCreateInstance(Type type, Boolean nonPublic, StackCrawlMark& stackMark)       at System.Activator.CreateInstance(Type type)       at Wintellect.Sterling.Serialization.SerializationHelper._Deserialize(BinaryReader br, CycleCache cache)       at Wintellect.Sterling.Serialization.SerializationHelper.Load(Type type, Object key, BinaryReader br, CycleCache cache)       at Wintellect.Sterling.Database.BaseDatabaseInstance.Load(Type type, Object key, CycleCache cache)       at Wintellect.Sterling.Database.BaseDatabaseInstance.Load(Type type, Object key)       at Wintellect.Sterling.Database.BaseDatabaseInstance.Load[T](Object key)       at BTT.PinPointTime.WinPhone.MainViewModel.LoadData()       at BTT.PinPointTime.WinPhone.App.StartupInitialization()       at BTT.PinPointTime.WinPhone.App.Application_Launching(Object sender, LaunchingEventArgs e)       at Microsoft.Phone.Shell.PhoneApplicationService.FireLaunching()       at Microsoft.Phone.Execution.NativeEmInterop.FireOnLaunching()

Load example: 

foreach (var item in App.Database.Query<Category, Guid>())
                {
                    //Categories.Add(item.LazyValue.Value);
                    Categories.Add(App.Database.Load<Category>(item.Key));
                }

Any idea what this would be about?

Mar 15, 2011 at 7:01 AM
Edited Mar 15, 2011 at 7:05 AM

Looks like I've sorted this out - I was incorrectly implementing my IsDirty flag.

If I implement it as a simple public method then my application runs without error:

 

public bool IsDirty()
        {
            return (this.State == State.Added || this.State == State.Modified || this.State == State.Deleted);
        }