I am looking through the Xamarin Sport app code and trying to understand some of the cool things they are doing in it. I cannot understand what IsDirty is being used for exactly. It gets defined here and implemented here and used in many places, such as here.
I read a little about and ICommand's IsDirty property so maybe it is a way to call an entire model as being dirty, but what implications does that have?
I also see it being used here which I am assuming is why they created it in the first place.
Thanks for y'all's insight into it.
They're just using it as a clever way to handle modification detection. Consider a "Save Changes" feature; you don't actually want to enable the "Save" button until something has changed, and you can key off the IsDirty property to test that.
Technically, you could handle this yourself by having a base class hook INotifyPropertyChanged.PropertyChanged and maintaining a dirty bit of your own (possibly in a base class), but rather than require all of their classes to have an IsDirty property that they may or may not need, they've made it an optional feature that a class can implement. For example, take a look at GameResult for an example of something that can't be changed, and therefore, can't be marked as dirty.
With this approach, you've minimized the amount of code you need to write to implement this functionality. All your derived classes need to do is derive from BaseNotify, implement IDirty, and call SetPropertyChanged(...) as the setter to set the private tracking field, signal to any observers that a property has changed, and automatically set the dirty bit.
NOTE: I did just make an interesting observation: while the implementation of the SetProperty extension method does set the IsDirty flag, the BaseNotify class' IsDirty implementation doesn't call anything to bubble up a PropertyChanged event for IsDirty, which means bindings against it won't get updated when it changes. I believe the fix would be for that extension method to invoke PropertyChanged with the property name "IsDirty":
if(dirty != null) {
dirty.IsDirty = true;
handler.Invoke(sender, new PropertyChangedEventArgs("IsDirty"));
// Yes, I'm a bad person for hard-coding the name.
}
Alternately, you could defer signaling the IsDirty change until after you signal the original property has changed. I just chose to keep it with the original logic.
I think it's relatively simple and you're on the right track: the purpose of that property is to have an easy way to know whether some property has been changed, so the whole object has to be saved. It's baked in to the way property changes are propagated, so you don't have to set it by yourself whenever a property value is being set.
tl;dr: You can use it to check if you your (view)model is worth a save operation ,-).
Related
I'm experimenting with MobX state management solution in Flutter. I really like its conciseness and its simplicity but I'm a bit concerned in the drawbacks its way of mutating the state can introduce.
Theoretically , we can force the state to be mutated only using actions and this is great because we can have a history of the changes using the spy feature the package provides.
However, actions are automatically created by the framework if we do not use a specific one. For example, in the code below, I created a counter store class and I used it in the main function to assign a new value for the counter without using a predeclared action. The stric-mode has been previously set to "always".
abstract class _Counter with Store {
#observable
int value = 0;
#action
void increment() {
value++;
}
}
final counter = Counter(); // Instantiate the store
void main() {
mainContext.config = mainContext.config
.clone(isSpyEnabled: true, writePolicy: ReactiveWritePolicy.always);
mainContext.spy((event) {
print("event name : " + event.name);
print("event type : " + event.type);
});
Counter counter = Counter();
counter.value = 10;
}
I was expecting an error to raise saying that it is not possible to change the state outside of action but this does not happen because an ad hoc action is created , called value_set, automatically. I'm wondering ,then, which is the point of forcing to use actions if it is possible to avoid using them. I mean, if we directly change the state, an action is created automatically and seen by the spy functionality making all the process more robust and predictable but, what if I want the state to be changed only by actions I previously implemented? Is there a way of doing so? For example, in the counter code I just provided , is there a way of making the counter incrementalbe only by 1? Because, in the way Mobx works, I could write everywhere in the code something like
counter.value = 10
and this will work just fine without any problems. Forcing people to use preset actions could increase the predicatability a lot and facilitate the teamwork too I think.
I tried to make the value variable private but it still remains accessible from the outside , also if annotated with #readonly.
Hm, that looks weird for me too, because it does work differently in MobX JS (exactly like you describing), but it seems that Dart MobX changed behaviour for single field values and they are automatically wrapped in actions now, yes.
Maybe there should be a optional rule to turn strict checking on again, it would make sense. I suggest you to create and issue or discussion on Dart MobX Github.
More info there: https://github.com/mobxjs/mobx.dart/issues/206
At the end, I found out that the behaviour I was looking for was obtainable with the #readonly annotation. Marking a variable with #readonly annotation avoids automatically creating its setter and getter methods. Moreover it requires the annotated variable to be private, denying the variable to be set directly.
Note: By the way, the way the Dart language is implemented, it is necessary to locate the Counter in a separate file to provide the desired behaviour, otherwise its private fields would be accessible anyway.
How is the PropertyChanged event used?
I'm wanting to evaluated the next state of a state machine whenever any property of the class is changed.
Regards Steve
PropertyChanged is part of the standard IPropertyNotifyChanged signaling.
If you want to create side effects if any change is done - consider setting "HasUserCode" on each attribute, Generate code, now you will find a partial method available for you to fill for Set and Get of attributes.
In a setter you can have side effects like running a trigger to step a state machine.
I'm fighting a few different design concepts within the context of MVVM that mainly stem from the question of when to initialize a ViewModel. To be more specific in terms of "initializing" I'm referring to loading values such as selection values, security context, and other things that could in some cases cause a few second delay.
Possible strategies:
Pass arguments to ViewModel constructor and do loading in the constructor.
Only support a parameterless constructor on the ViewModel and instead support initialize methods that take parameters and do the loading.
A combination of option 1 and 2 where arguments are passed to the ViewModel constructor but loading is deferred until the an Initialize method is called.
A variation on option 3 where instead of parameters being passed to the ViewModel constructor they are set directly on properties.
Affect on ViewModel property getters and setters
In cases where initialization is deferred there is a need to know whether the ViewModel is in a state that is considered available for which the IsBusy property generally serves just as it does for other async and time consuming operations. What this also means though is that since most properties on the ViewModel expose values retrieved from a model object that we constantly have to write the following type of plumbing to make sure the model is available.
public string Name
{
get
{
if (_customerModel == null) // Check model availability
{
return string.Empty;
}
_customerModel.Name;
}
}
Although the check is simple it just adds to the plumbing of INPC and others types of necessities that make the ViewModel become somewhat cumbersome to write and maintain. In some cases it becomes even more problematic since there may not always be a reasonable default to return from the property getter such might be the case with a boolean property IsCommercialAccount where if there is no model available it doesn't make sense to return true or false bringing into question a whole slew of other design questions such as nullability. In the case of option 1 from above where we passed everything into the constructor and loaded it then we only need to concern ourselves with a NULL ViewModel from the View and when the ViewModel is not null it is guaranteed to be initialized.
Support for deferred initialization
With option 4 it is also possible to rely on ISupportInitialize which could be implemented in the base class of the ViewModel to provide a consistent way of signaling whether the ViewModel is initialized or not and also to kick off the initialization via a standard method BeginInit. This could also be used in the case of option 2 and 3 but makes less sense if all initialization parameters are set all in one atomic transaction. At least in this way, the condition shown above could turn into something like
How the design affects IoC
In terms of IoC I understand that options 1 and 3 can be done using constructor injection which is generally preferred, and that options 2 and 4 can be accomplished using method and property injection respectively. My concern however is not with IoC or how to pass in these parameters but rather the overall design and how it affects the ViewModel implementation and it's public interface although I'd like to be a good citizen to make IoC a bit easier if necessary in the future.
Testability
All three options seem to support the concept of testability equally which doesn't help much in deciding between these options although it's arguable that option 4 could require a more broad set of tests to ensure proper behavior of properties where that behavior depends on the initialization state.
Command-ability
Options 2, 3, and 4 all have the side effect of requiring code behind in the View to call initialization methods on the ViewModel however these could be exposed as commands if necessary. In most cases one would probably be loading calling these methods directly after construction anyways like below.
var viewModel = new MyViewModel();
this.DataContext = viewModel;
// Wrap in an async call if necessary
Task.Factory.StartNew(() => viewModel.InitializeWithAccountNumber(accountNumber));
Some other thoughts
I've tried variations on these strategies as I've been working with the MVVM design pattern but haven't concluded on a best practice yet. I would love to hear what the community thinks and attempt to find a reasonable consensus on the best way forward for initializing ViewModels or otherwise dealing with their properties when they are in an unavailable state.
An ideal case may be to use the State pattern where the ViewModel itself is swapped out with different ViewModel objects that represent the different states. As such we could have a general BusyViewModel implementation that represents the busy state which removes one of the needs for the IsBusy property on the ViewModel and then when the next ViewModel is ready it is swapped out on the View allowing that ViewModel to follow the stategy outlined in option 1 where it is fully initialized during construction. This leaves open some questions about who is responsible for managing the state transitions, it could for example be the responsibility of BusyViewModel to abstract something similar to a BackgroundWorker or a Task that is doing the initialization itself and will present the internal ViewModel when ready. Swapping the DataContext on the view on the other hand may require either handling an event in the View or giving limited access to the DataContext property of the View to BusyViewModel so it can be set in the traditional state pattern sense. If there is something similar that people are doing along these lines I would definitely like to know because my google searching hasn't turned up much yet.
My general approach to object oriented design, whether I am creating a view model, or an other type of class is that; Everything that can be passed to the constructor, should be passed to the constructor. This reduces the need to have some sort of IsInitialized state and makes your objects less complex. Sometimes certain frameworks make it hard to follow this approach, IoC containers for example (although they should allow constructor injection), but I still adhere to it as a general rule.
What is the best way of adding a new object in the entity framework. The designer adds all these create methods, but to me it makes more sense to call new on an object. The generated CreateCustomer method e.g. could be called like this:
Customer c = context.CreateCustomer(System.Guid.NewGuid(), "Name"));
context.AddToCustomer(c);
where to me it would make more sense to do:
Customer c = new Customer {
Id = System.Guid.NewGuid(),
Name = "Name"
};
context.AddToCustomer(c);
The latter is much more explicit since the properties that are being set at construction are named. I assume that the designer adds the create methods on purpose. Why should I use those?
As Andrew says (up-voted), it's quite acceptable to use regular constructors. As for why the "Create" methods exist, I believe the intention is to make explicit which properties are required. If you use such methods, you can be assured that you have not forgotten to set any property which will throw an exception when you SaveChanges. However, the code generator for the Entity Framework doesn't quite get this right; it includes server-generated auto increment properties, as well. These are technically "required", but you don't need to specify them.
You can absolutely use the second, more natural way. I'm not even sure of why the first way exists at all.
I guess it has to do with many things. It looks like factory method to me, therefore allowing one point of extension. 2ndly having all this in your constructor is not really best practice, especially when doing a lot of stuff at initialisation. Yes, your question seems reasonable, i even agree with it, however, in terms of object design, it is more practical as they did it.
Regards,
Marius C. (c_marius#msn.com)
When setting a property on an entity object, it is saving the value to the database even if the value is exactly the same as it was before. Is there anyway to prevent this?
Example:
If I load a Movie object and the Title is "A", if I set the Title to "A" again and SaveChanges() I was hoping that I wouldn't see the UPDATE statement in SqlProfiler but I am. Is there anyway to stop this?
Yes, you can change this. Doing so isn't trivial, however, in the current version of the Entity Framework. It will become easier in the future.
The reason you're seeing this behavior is because of the default code generation for the entity model. Here is a representative example:
public global::System.Guid Id
{
get
{
return this._Id;
}
set
{
// always!
this.OnIdChanging(value);
this.ReportPropertyChanging("Id");
this._Id = global::System.Data.Objects.DataClasses
.StructuralObject.SetValidValue(value);
this.ReportPropertyChanged("Id");
this.OnIdChanged();
}
}
private global::System.Guid _Id;
partial void OnIdChanging(global::System.Guid value);
partial void OnIdChanged();
This default code generation is reasonable, because the Entity Framework doesn't know the semantics of how you intend to use the values. The types in the property may or may not be comparable, and even if they are, the framework can't know how you intend to use reference equality versus value equality in all cases. For certain value types like decimal, it's pretty clear, but in a general sense it's not obvious.
You, on the other hand, know your code, and can customize this some. The trouble is that this is generated code, so you can't just go in and edit it. You need to either take over the code generation, or make it unnecessary. So let's look at the three options.
Take over the code generation
The essential approach here is to create a T4 template which does the code behind, and that the default code generation from the Entity Framework. Here is one example. One advantage of this approach is that the Entity Framework will be moving to T4 generation in the next version, so your template will probably work well in future versions.
Eliminate code generation
The second approach would be to eliminate cogeneration altogether, and do your change tracking support manually, via IPOCO. Instead of changing how the code is generated, with this approach you don't do any code generation at all, and instead provide change tracking support to the Entity Framework by implementing several interfaces. See the linked post for more detail.
Wait
Another option is to live with the Entity Framework the way it is for the time being, and wait until the next release to get the behavior you desire. The next version of the Entity Framework will use T4 by default, so customizing the code generation will be very easy.
According to MSDN:
The state of an object is changed from
Unchanged to Modified whenever a
property setter is called. This occurs
even when the value being set is the
same as the current value. After the
AcceptAllChanges method is called, the
state is returned to Unchanged. By
default, AcceptAllChanges is called
during the SaveChanges operation.
Looks like you'll want to check the value of properties on your Entity objects before you update to prevent the UPDATE statement.
At a generic level, if your entities are implementing INotifyPropertyChanged, you don't want the PropertyChanged event firing if the value is the same. So each property looks like this :-
public decimal Value
{
get
{
return _value;
}
set
{
if (_value != value)
{
_value = value;
if (_propertyChanged != null) _propertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
}
Hope that's relevant to Entity Framework.
One thing you can do is just wrap the property yourself using a partial class file, and then use your property instead of the first one:
public sealed partial class MyEFType {
public string MyWrappedProperty {
get {
return MyProperty;
}
set {
if (value == MyProperty)
return;
MyProperty = value;
}
}
}
It wouldn't be very practical to do this to every property, but if you have a need to detect that a particular property has actually changed and not just been written to, something like this could work.