Computed Property problem

Aug 23, 2015 at 2:36 AM
I have a computed property in a entity with the persist atrribute, the first time i save the value is persisted, if i load the entity and change values to the computed property is changed it works fine in memory but it is not persisted to database when i save again.

Thanks
Aug 23, 2015 at 5:35 AM
I will look at it, thx
Aug 23, 2015 at 1:59 PM
Another thing, when i have a computed column using a IList<T> collection property, like the sum of the lines, i use the DependsOn that property but when i add or remove from that collection the PropertyChanged notification is not fired, is this a bug or does it not work with collections?

Regards
Aug 24, 2015 at 1:46 AM

Yeah list props are not real props so it wouldn't work

Aug 25, 2015 at 12:43 PM
Did you confime the problem with the persist of calculated property?
Aug 25, 2015 at 5:29 PM
not yet, sorry, just got back from vacation, give me a couple more days pls
Aug 26, 2015 at 8:29 PM
I cannot reproduce it, it seems to be updated fine. Here is my test, I extended IDriver entity in misc tests:
  [Entity]
  public interface IDriver {
    [PrimaryKey, Auto]
    Guid Id { get; set; }

    [Size(30), Unique(Alias = "LicenseNumber")]
    string LicenseNumber { get; set; }

    [Size(Sizes.Name)]
    string FirstName { get; set; }
    [Size(Sizes.Name)]
    string LastName { get; set; }

    [OneToMany("Owner")]
    IList<IVehicle> Vehicles { get; set; }

    //DependsOn is optional, used for auto PropertyChanged firing
    [Computed(typeof(MiscTestsExtensions), "GetFullName"), DependsOn("FirstName,LastName")] 
    string FullName { get; }
    //Persistent computed property
    [Computed(typeof(MiscTestsExtensions), "GetLicenseHash", Persist=true), DependsOn("LicenseNumber")]
    int LicenseHash { get; }
  }
and then execute the following:
      //Computed persistent prop; verify that column (LicenseHash) is updated in database after we update other prop (LicenseNumber) it dependent on
      var dr2 = session.NewDriver("Z002", "John", "Dow");
      var oldHash = dr2.LicenseHash;
      session.SaveChanges();
      //Change it
      dr2.LicenseNumber = "Z002X";
      session.SaveChanges(); 
      //get hash without loading entity
      var hashObj = session.EntitySet<IDriver>().Where(d => d.Id == dr2.Id).Select(d => new { Hash = d.LicenseHash }).Single(); 
      var newHash = hashObj.Hash;
      Assert.AreNotEqual(oldHash, newHash, "Expected different hash.");
      var expectedHash = Util.StableHash("Z002X");
      Assert.AreEqual(expectedHash, newHash, "Invalid new hash");
everything seems to work OK, I went step-by-step and verified when and how hash column changes in the database
Aug 26, 2015 at 8:31 PM
Another thing - you do have a DependsOn attr on your computed property, right?
Aug 26, 2015 at 10:25 PM

Yes but it is on IList<> column

Ruben Alves




On Wed, Aug 26, 2015 at 12:31 PM -0700, "rivantsov" <[email removed]> wrote:

From: rivantsov

Another thing - you do have a DependsOn attr on your computed property, right?
Aug 26, 2015 at 10:28 PM
wait, what list column? which column is list one - the computed one or the col that computed column depends on? As I said before, DependsOn would not work on/ or with target of list columns, because list columns are not real columns
Aug 27, 2015 at 1:40 AM
Here is a actual senario where a computed column is nedded.

interface IOrder
{
    [PrimaryKey, Auto]
    Guid Id { get; set; }

    [EntityRef("EntidadeID")]
    IEntidade Customer { get; set; }

    IList<Details> Details { get; set; } 

    [Computed(typeof(OrderExtension), "GestTotal", Persist = true))]
    decimal Total { get; }

}
the GetTotal sums all the "Details" colums Qtd x Unit Price giving the orders total.

When i save it works ok, if i change anything in the Detais list it calculates the total correctly but it does not persist the changes, only the inicial insert works, the update dos not include the calculated columns. If i read the calculated column the value is updated but it is not persisted on savechanges

Any change to the Details IList needs to recalculate and send PropertyChanged notification to the columns that use that IList (That is the way that i think it is usable ), but the problem is that Vita does not Update the caclulated column if i change any value of the IList or add or remove items to the list.
Aug 27, 2015 at 1:48 AM
Edited Aug 27, 2015 at 1:49 AM
I think that if you persist all the Computed columns every time the problem is resolved, if not there is "not real usefull" use for the example you gave, the first name / last name example, it is a prof of concept. calculating total of order detais in a order is a "better" use senario to test it.

Regards
Aug 27, 2015 at 2:18 AM
There are cases when certain conveniencies (like Computed property) work well, in other cases they don't.
Just think about this. What if I load a single Detail, modify quantity and save it. The Order entity is not loaded, there is no way the Total calculation to be activated. So this is NOT a good case for using Computed. You should instead hook to Saving event on IDetail entity and recalc the order total. I need to go now, will provide more details later
Aug 27, 2015 at 11:58 AM
Looks like a good solution, how can i hook to the saving event?

Regards
Aug 27, 2015 at 2:53 PM
I removed the computed columns and made a helper method to recalculate the totals before saving changes and it is now working fine, looks like my undestanding of the computed property's was incorrect for what i needed it for.

thanks, keep up the good work :)
Aug 27, 2015 at 5:28 PM
yeah, right move. I looked at using this Saving event, and did not see a good efficient solution. The problem is to get perfect timing for the call to recompute, and to make sure it is called once. So making recalculation explicit and calling it directly is the best approach. I may revisit this scenario later and see if things can be improved to handle situations like this.
and thanks for the review!
Aug 27, 2015 at 7:00 PM
If you ever need any help with testing or what ever i can help.

Regards