usschad wrote:
Sorry to post on this old thread, but I was reviewing it and wanted to add that this works when you are using ForcedCurrentValueWrite on a fetched entity.
However, if you are doing this on a new entity you must set entity.Fields.State = EntityState.Fetched
. Otherwise, the DBValue wasn't getting set.
In my use case, I am writing unit tests, and want to fake a fetched entity. And this is how it was done:
public static void MakeAppearFromDb<T>(this T entity) where T : IEntity2
{
entity.IsNew = false;
entity.Fields.State = EntityState.Fetched; // this is the important part we were missing for the below code to work correctly.
foreach (var field in entity.Fields)
{
var val = field.CurrentValue;
entity.Fields.ForcedValueWrite(field.FieldIndex, val, val);
}
entity.IsDirty = false;
return entity;
}
The reason the state has to be set to Fetched
isn't for the writing of the values, but for the reading of the DbValue When the entity isn't marked as 'Fetched', the DbValues are by definition undefined, so they will always return 'null'. Setting the fields' state to Fetched, means that the DbValues in the Fields object are from the DB and it will return the DbValue that's stored in the DbValues array of the Volatile Data structure inside the Fields object.
In v5 we refactored the internal data structures for the fields to make them much more efficient. Before that each field contained its own value, but after that we store the values in an array (two arrays in fact, DbValues and CurrentValues). The DbValues array isn't created till it's written to. This has the advantage that we can just store the whole array read from the Db in 1 go (so fetches are much faster) and it doesn't create a lot of objects to store the values.
Using Field objects as separate objects is still possible, to keep backwards compatibility, however it's no longer needed. Your foreach loop creates new entityfield2 objects as they're not there after an entity has been created or data has been fetched. It's more efficient to do:
public static void MakeAppearFromDb<T>(this T entity) where T : IEntity2
{
entity.IsNew = false;
entity.Fields.State = EntityState.Fetched; // this is the important part we were missing for the below code to work correctly.
for(int i=0;i<entity.Fields.Count;i++)
{
var val = entity.Fields.GetCurrentValue(i);
entity.Fields.ForcedValueWrite(i, val, val);
}
entity.IsDirty = false;
return entity;
}
as this way no entity field objects are created. While it isn't really important in a unit test but it might be in a high-performance code path where many entities are created and fields are set.