as I often let LinqToSql generate partial entity classes, I am wondering if my practice of adding additional properties via code is correct and if there is a better way of doing the same thing? I am also wondering what is the difference between accessing the values of other properties using this.PROPERTY_NAME vs _PROPERTY_NAME?
In my web app I keep using this.PROPERTY_NAME, but I am wondering if that is, as I already said in opening sentence, the proper approach I should be using. Also, What is _PROPERTY_NAME and when do we use it?
Example:
public partial class User
{
public bool IsThisProper {
get{
return this.SomeIntProperty == 10; // I usually use this
}
}
public bool WhenToUseThisApproach {
get{
return _SomeIntProperty == 10; // What is this in comparison to above?
}
}
}
One is the property, and the other is the private backing field in which that property stores it's value. If you want to execute whatever code the property has in it's getter/setter, then use the property, if you don't, then don't. Chances are you want to use the property, not the field, especially with setting (setting it triggers the property changed event, so about the only time to use the property is if you don't want that event raised).
Related
I'm looking for best practices in regards to having a class which has a flag which decides whether an operation can be performed on that class or not. This entire class will be returned in WCF REST services as well used in a Silverlight GUI via RIA Services in order to set certain action buttons to be enabled or disabled for the user. I want to know best practices for setting up a class in this way. For example:
public class SomeCustomerClass
{
private bool _canResetCustomer;
public bool CanResetCustomer
{
get { return _canResetCustomer; } //TODO: Place GET logic here from DB if it's null
set { _canResetCustomer = value; }
}
if (this._canResetCustomer)
{
ResetCustomer();
}
...
See my "TODO"? I need to determine if the bool has been set. If it hasn't been set, I need to get the eligibility of this customer for reset from a list of data-based rules from the database. The way I see it, there are two options, both of which I've used before:
Define another bool which tracks whether CanReset has been set or not, like so:
public bool _canResetSet { get; set; }
Change my bool to a nullable type. I think in the constructor I'd have to instantiate the object with _canResetCustomer = null. Maybe?
Not sure why I'm asking this question except that maybe I'm just shy of nullable types. Does this entire dilemma speak to other issues with the way I design things? I commonly use this method of flagging in webforms applications as well.
Go with nullable. If its HasValueequals false, go check the db. Setting it to null in the constructor isn't necessary, as it is the default.
In an old WPF project I have a class with Properties like this:
private string _name = "";
public string Name
{
get { return _name; }
set
{
string cleanName = clsStringManip.CleanText(value, true);
if (cleanName != _name)
{
_name = cleanName;
}
}
}
Where every time the name changes, I ensure that the value is "cleaned". Putting it in the property ensures I never forget to clean the string before setting the property on the object.
Now I am recreating this system using MVC5 and EntityFramework6.1 using DatabaseFirst.
So all the properties are autogenerated by EF. How then can I add the equivalent CleanText function to my properties without editing the autogen code? - as I'll lose these changes next time I change my database and resync.
All I can find via Google is a way add data annotations via MetadataType and partial classes but this doesn't answer my question.
I tried to add the above code into a partial class but get the error:
The type XXX already contains a definition for Name
The only way I can think is to create a bunch of SetProperty() functions but this is dirty and you can never ensure other developers (or myself) will remember to use them.
Disclaimer: I haven't used EF 6 yet.
Let me answer this in two parts. First, I will tell you how to do this. Then I will tell you why I don't think you should do this. :-)
HOW:
As you discovered, you cannot create another Name property. You need to modify the way the EF generates the code, so that it gives you a place to insert your new code. Depending on how you are using the EF, it often generates Validate() method calls or OnPropertyChanged() calls. You may be able to do what you want inside of those methods.
If you can't do this in Validate() or OnPropertyChanged(), you could change the T4 template to generate something like this:
private string _name = "";
public string Name
{
get { return _name; }
set
{
string cleanName = value;
Cleanup_Name(ref cleanName);
if (cleanName != _name)
{
_name = cleanName;
}
}
}
private partial void Cleanup_Name(ref string);
This gives you a partial method that you can then implement as you see fit. So for any property you want to customize, you can now add another file to your project that does this:
public partial class MyEntity {
void Cleanup_Name(ref string name)
{
// Put your logic in here to fixup the name
}
}
If you do not write the above code block, then the partial method is simply a no-op. (Partial methods must return void, hence the use of a ref parameter).
WHY NOT?
The advantage of this method is that it is totally transparent to the developer. The property is just magically changed. But there are several disadvantages:
Some controls expect that if they call name = "123" that if they get the name back, it is "123" and will fail if this happens. Values are changing but no PropertyChanged event fired. If you do fire the PropertyChanged, then they sometimes change the value back. This can cause infinite loops.
There is no feedback to the user. They typed in one thing, and it looked right, but now it says something different. Some controls might show the change and others won't.
There is no feedback to the developer. The watch window will seemingly change values. And it is not obvious where to see the validation rules.
The entity-framework itself uses these methods when it loads data from the database. So if the database already contains values that don't match the cleanup rules, it will clean them when loading from the database. This can make LINQ queries misbehave depending on what logic is run on the SQL server and what logic is run in the C# code. The SQL code will see one value, the C# will see another.
You might also want to look into what the Entity-Framework's change tracking does in this case. If a property set does a cleanup while loading values from the database, does it consider that a change to the entity? Will a .Save() call write it back to the database? Could this cause code that never intended to change the database to suddenly do so?
ALTERNATIVE
Instead of doing this, I suggest creating a Validate() method that looks at each property and returns errors indicating what is wrong. You could also even create a Cleanup() method that fixes the things that are wrong. This means the cleanups are no longer transparent, so the developer must call them explicitly. But that is a good thing: the code isn't changing values without them realizing it. The person writing the business logic or the UI knows at what point the values will change, and can get a list of why.
The only way you can achieve this is by creating a new property you actually use in your application. Perhaps you can hide the original property in the designer. The actual property you use could look like this:
public string ExternalName
{
get { return Name; }
set
{
string cleanName = clsStringManip.CleanText(value, true);
if (cleanName != Name)
{
Name = cleanName;
}
}
}
As an alternative, you can use POCO classes:
If you want to keep using database-first, check this answer
Use code-first for an existing database, see this detailed guide
Add partial to the generated class.
Change the scope of Name in the generated class from public to internal.
Add the following in the same assembly:
public partial class classname
{
[NotMapped]
public string CleanName
{
get { return Name; }
set
{
var cleanName = clsStringManip.CleanText(value, true);
if (cleanName != Name)
Name = cleanName;
}
}
}
Caveat: you'd have to remember to do steps 1-2 every time you regenerated your POCOs ... I'd seriously consider Code First to Existing Database.
EDIT
Optionally:
Rename Name as InternalName in the generated classname; decorate it with [Column("Name")].
Rename CleanName as Name in the partial class under your control.
Caveat in 4 becomes "remember to do steps 1, 2, and 5 every time you regenerate POCOs".
This approach has the added benefit of not having to modify any of your client code (i.e., use of Name remains Name). And I'd still strongly consider Code First to Existing Database.
I am working with WPF and MVVM, and so have a lot of properties in my view models that are bound to stuff in the view. The majority of these properties look like this...
private DateTime _newRevisionDate = DateTime.Now;
public DateTime NewRevisionDate {
get {
return _newRevisionDate;
}
set {
if (_newRevisionDate != value) {
_newRevisionDate = value;
RaisePropertyChanged(ViewModelUtils.GetPropertyName(() => NewRevisionDate));
}
}
}
I'm using MvvmLight, which is where the RaisePropertyChanged() method comes from, and have used the ViewModelUtils.GetPropertyName() method to create a string from the property name, avoiding the need for magic strings.
Now, the problem is that if I add a few such properties to a view model, I end up with a large amount of almost identical code. This just cries out for some clever refactoring, so I can just use a single line of code to define each property.
However, I haven't been able to find any way to do this yet. What would be nice is to be able to do something like the standard C# automatic properties...
public DateTime NewRevisionDate { get; set; }
...but have it call RaisePropertyChanged() whenever the property is set to a new value.
Anyone any ideas? Thanks
This just cries out for some clever refactoring, so I can just use a single line of code to define each property.
Well you can make it a single line now. It's just a very long line :)
C# 5 makes this slightly easier with caller info attributes, so you don't need the GetPropertyName part - and that's the ugliest part of your current code.
The other thing you could do would be:
set
{
_newRevisionDate = PossiblyFireEvent(RaisePropertyChanged, _newRevisionDate, value);
}
where PossiblyFireEvent would take the property name as an optional parameter using the caller info attributes, RaisePropertyChanged as a delegate to execute if the two values were unequal, and always return value. Not sure it's worth it though.
Usually, when I code property of classes that could be edited by the user with a binding of some kind... To prevent executing of GUI logic, I don't allow to assign the same value to the property:
public PMSAccountingYear AccountingYear{
get { return _accountingYear; }
set{
if(_accountingYear == value)
return;
_accountingYear = value;
NotifyOtherProperties();
LogChanges();
EmallToTheBoss();
Errr();
BlowBombInTheGarden();
Etc();
}
}
The condition check doesn't look elegantly, and cannot be detected with any automatic code analysis.
Can you please suggest a better case?
With one of the attributes maybe?
What you are doing is perfectly fine; this is the common way to implement setters for things like INotifyPropertyChanged (aee also the example on that page).
As the value did not change, there is no need to actually update the backing field and especially not to notify others of a “changed” value.
I've got a WPF app that's using INotifyPropertyChanged to signal property updates. What I like about it is that it gives you the ability to signal a property change without invoking all of the setter code. This is handy when you've got two linked fields that update each other or when you've got code that saves changes on every setter and you don't want to trigger the save multiple times for what is essentially one change by the user.
However the obvious weakness of this approach is that a mistake in the property name or on which viewmodel you send the notification to will mess you up and only show up and runtime.
I looked into dependency properties but was unable to find anything that lets you do a "soft update": let the UI know that the property has changed but avoid calling all the code that would normally run when a UI causes a change in the viewmodel.
Is there some way I can get a property system that allows soft updates and catches notification problems at compile-time?
If the underlying problem is mistakes in the property name, there are compile-time solutions, like making the "property name" parameter an expression tree instead of a string.
http://michaelsync.net/2009/04/09/silverlightwpf-implementing-propertychanged-with-expression-tree
The Caliburn.Micro library also includes this approach in its PropertyChangedBase class.
I like Foson's solution for "early binding" vis a vis the property names and eliminating the need to keep a string copy of your property name around. This is the core of the implementation I, personally, use:
public virtual string GetName<T>(Expression<Func<T>> expression)
{
return GetMemberName(expression);
}
/// <summary>Abstraction for actually finding the name of the target of the expression</summary>
private static string GetMemberName<T>(Expression<Func<T>> expression)
{
if (expression != null)
{
var myMemberExpression = expression.Body as MemberExpression;
if (myMemberExpression != null && myMemberExpression.Member != null)
{
return myMemberExpression.Member.Name;
}
}
return string.Empty;
}
This code resides in a class called NameResolver, which my ViewModelBase class wraps with
NotifyChange(Expression<Func<T>> expression)
Then client code looks something like:
private int _myBindable;
public int MyBindable { get { return _myBindable; } set { _myBindable = value; NotifyChange(() => MyBindable); }
As to the notion of separating GUI notification from updating underlying stuff, you can invoke those NotifyChange() methods elsewhere than the property setter when whatever happens in your code that should trigger UI update happens. So, GUI sets your property, which triggers some logic, but you don't raise change notification there -- you raise it from wherever, specifically, you want to inform the UI about something.