Philosofical question + practical issues
OndrejValenta opened this issue · 4 comments
Hi,
I was trying out your library yesterday and I'm pretty impressed but I have some questions.
I was trying a simple scenario, fetch items from SharePoint, map them to simple POCO object, make it trackable via AsTrackable() so I know what properties have changed, accept the initial version of data via AcceptChanges() and then insert it to a tracked collection of this objects.
var items = op
.GetItems();
var trackableStock = new TrackableStock();
foreach (var item in items)
{
var model = new TrackableStockItem();
var trackedModel = model.AsTrackable();
trackedModel.Id = item.Id;
trackedModel.Name = item["Title"].ToString();
trackedModel.CastToIChangeTrackable().AcceptChanges();
trackableStock.Items.Add(trackedModel);
}
The problem with this approach, which I find correct because when there has to be a parameterless constructor then there has to be a way to accept the initial data, is that tracked collection then does not recognize these items as added but as unchanged.
So say I want to create a new item then I'll create a new POCO object, change it to tracked POCO object, set the data and accept the changes and then push it into the collection so when I'm saving all items I know exactly which are new/added and which are changed.
I mean there should be another way how to track which objects are added then using "IsChanged" property, in my opinion.
Another thing is that the code is getting quite talkative but this is perhaps because I'm not sure what I'm doing.
public class TrackableStock
{
public IList<TrackableStockItem> Items { get; } = new List<TrackableStockItem>().AsTrackable();
}
...
trackableStock.Items[0].Amount = 15; // this works fine
trackableStock.Items.Remove(trackableStock.Items[1]); // this works fine as well
var stockItem = new TrackableStockItem() { Name = "Newly created item" }.AsTrackable(); // I would love to see this method like AsTrackable(initialValues: true);
stockItem.CastToIChangeTrackable().AcceptChanges(); // this feels akward to me if I have to do it every single time, one can get use to it but still..
trackableStock.Items.Add(stockItem); // does not tracked properly when the object has accepted changes
Do I have to Cast.. it to trackable object everytime I want to accept changes and undo them? That's a lot of code noise.
I would probably create a factory class for new POCO instances for example Is.Tracked(); just to make it simpler. or perhaps an extension method for an Object class, so I could create NewTracked() object anywhere.
I'm using the latest beta NuGET.
I am not sure I fully understand your concerns, does the following help?
void Main()
{
var items = GetItems();
var trackableStock = new TrackableStock();
//Option 1
foreach (var item in items)
{
var model = new TrackableStockItem();
model.Id = item.Id;
model.Name = item.Name.ToString();
trackableStock.Items.Add(model);
}
trackableStock.Items.CastToIChangeTrackableCollection().AcceptChanges();
//or
trackableStock.AcceptChanges();
Console.WriteLine($"IsChanged: {trackableStock.Items.CastToIChangeTrackableCollection().IsChanged}");
//option 2
IList<TrackableStockItem> trackableStockList = items
.Select(i => new TrackableStockItem { Id = i.Id, Name = i.Name })
.ToList()
.AsTrackable();
Console.WriteLine($"IsChanged: {trackableStockList.CastToIChangeTrackableCollection().IsChanged}");
}
public TrackableStockItem[] GetItems() => new[]
{
new TrackableStockItem
{
Id = 0,
Name = "Test0"
},
new TrackableStockItem
{
Id = 1,
Name = "Test1"
}
};
public class TrackableStock
{
public IList<TrackableStockItem> Items { get; } = new List<TrackableStockItem>().AsTrackable();
public void AcceptChanges() => Items.CastToIChangeTrackableCollection().AcceptChanges();
}
public class TrackableStockItem
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
Closed due to inactivity
@OndrejValenta Forgive me if I'm wrong, but wouldn't the answer be to create the instance of your object and set all the properties before you cast it as trackable? ie, perform all your initialization on your object to set it's initial state, and then make it trackable so that becomes your starting point and only changes after that point will then trigger the change tracking?
it
I wish I remembered this code and question but it is so blury. Anyway, what you are saying sounds right.