Server error in MVC app due to public property getter/setter - c#

public int IndicationCalculatorGroupId { get; set; }
When I have it like that, it works.
public int IndicationCalculatorGroupId
{
get
{
return IndicationCalculatorGroupId;
}
set
{
IndicationCalculatorGroupId = value;
SelectList tempList = Chatham.Web.Models.Shared.DropDownData.IndicationsGroup(SessionManager.Company.EntityID, ICConstants.IndicationsCalculatorGroupType);
foreach (SelectListItem item in tempList)
{
if (value.ToString() == item.Value)
{
GroupDisplayName = item.Text;
break;
}
}
}
}
That however doesn't seem to work. Basically, I wanted to customize the setter so that when it was set, it would use the value to set it, along with searching for the value in a SelectList to set another property with another value.
Am I doing this right?

If you want custom getter/setter you must create underlying field. Otherwise calls to IndicationCalculatorGroupId inside getter will produce StackOverflow.

Related

How can I update a database value when I change the value of a property?

I have this code:
public static class Settings
{
public static int Trk5 { get; set; }
}
Settings.Trk5 = 2;
db2.Update(new Setting { "Trk5", Value = val.ToString() });
Would it be a good idea to somehow combine the updating of the database with the setting of the variable and if so how could I do that?
Can I combine the db2.Update into the set; somehow?
You could let the property save itself in its setter (like #Alsein proposed). You would need to convert your auto-property to a full property for that.
Perhaps this might work:
public static class Settings
{
private static int trk5;
public static int Trk5
{
get { return trk5; }
set
{
if (trk5 != value)
{
trk5 = value;
db2.Update(new Setting { "Trk5", Value = value.ToString() });
}
}
}
}
Settings.Trk5 = 2;
However, I doubt if your db2.Update call will work this way. You are creating a new Setting instance there, but you did not specify the property name for the "Trk5" value...
You need to call the Update method within the property.
If you want it to be automatically applied to every single properties, consider the following solutions:
Make a proxy that raises the changing event dynamically at runtime.
Inserting the notification statically at build time.

If I have a property do I need a field as well?

So after the availability of automatic implementation, and initialization of a property, do I even need a field for my property?
This seems much cleaner:
class A {
public int X {
get;set;
} = 1;
}
Than this:
class A {
int x = 1;
public int X {
get {
return x;
}
set {
x = value;
}
}
}
In the first case, the compiler is already providing a backing field - it's just implicit (and it's given a name that you can't refer to in code). Note that there has to be a backing field in the generated code, as a property itself is really just a pair of methods with some metadata linking them - the presence of a property does not add any state to the object. State is only stored in fields.
It's even cleaner when written on one line - I'd usually see this as:
class A
{
public int X { get; set; } = 1;
}
You dont need a backing field in this situation, but if you want to manipulate the Property with e.g a OnPropertyChanged() then you need to have a backing field
public int X {
get {
return x;
}
set {
x = value;
OnPropertyChanged()
}
}

Adding Properties into a List or Collection

I have come across a situation where I probably needed to add properties(of a class) in a list to invoke them manually(or you can say, I need to assign there values(setter)). That is why because, I don't even know which properties is to set the values, but they are decided at runtime. So far I am trying to find out the solution here and there but still I don't get any article that even hints me a work around for this purpose.
Here's what I want to do exactly (mentioned as comments)-
public class DemoClass
{
IList<Properties> _listOfProps;
private int _iFirstProperty;
private string _iSecondProperty;
public DemoClass()
{
_listOfProps = new List<Properties>();
}
public int FirstProperty
{
get
{
return _iFirstProperty;
}
set
{
_iFirstProperty = value;
// Here I want to add this property into the list.
_listOfProps.Add(FirstProperty);
RaisePropertyChanged("FirstProperty");
}
}
public string SecondProperty
{
get
{
return _iSecondProperty;
}
set
{
_iSecondProperty = value;
RaisePropertyChanged("SecondProperty");
}
}
public void HandleChangedProperties()
{
foreach (var list in _listOfProps)
{
// Here I want to invoke the property. ie. sets the 'value' of this property.
list.Invoke(value)
}
}
}
I know, I can use Func to add in the list like- but I can't go with this.
List<Func<int>> listOfFunc = new List<Func<int>>();
listOfFunc.Add(() => { return 0; }); // Adds using lambda expression
listOfFunc.Add(temp); // Adds as a delegate invoker
private int temp()
{
return 0;
}
from MSDN
Properties can be used as if they are public data members, but they
are actually special methods called accessors.
if properties are internally methods, Why they can't be added as List of Func<>
Also, if there's no way I can do that without using Reflection (by getting PropertyInfo list), why Microsoft hasn't designed this in C#?
You can either keep a list of PropertyInfo values and later set the value of the properties using reflection, or you can keep a list of setter delegates (which effectively just forward the value to the real, hidden setter).
For example:
IList<Action<object>> listOfSetters;
listOfSetters.Add(o => this.FirstProperty = (int)o);
// and then:
listOfSetters[0](42); // FirstProperty = 42

Change an item property received from a linq query

I need to change the value of an item of a list returned by a query... It must be simple, but i can´t see it using linq.
The list is composed by elements of this structure:
public struct HeaderButton
{
public string content {get; set;}
public BitmapImage icon {get; set;}
public PageContainerFactory.ContainerType containerType {get; set;}
public bool IsSelected { get; set; }
}
private List<HeaderButton> _headerButtons;
public List<HeaderButton> HeaderButtons
{
get
{
if (_headerButtons == null)
_headerButtons = new List<HeaderButton>();
return _headerButtons;
}
set { _headerButtons = value; }
}
I´ve tried this:
HeaderButtons.First(x => x.containerType == CurrentContainer.CType).IsSelected = true;
And the compiler tells me:
Cannot modify the return value of 'System.Linq.Enumerable.First(System.Collections.Generic.IEnumerable, System.Func)' because it is not a variable
And now the query that i´m trying:
var h = HeaderButtons.First(x => x.containerType == CurrentContainer.CType);
h.IsSelected = true;
I had to take the element in a var because of the compiler error. And doing it as represented in the code above, obviously "h" does not points to the "HeaderButtons" real element since it is a new HeaderButton object and not a reference.
Following your comments, i decided to make a nested class in place of the structure since this kind of objects are not used outside of the content class, and now that is a class (object reference) and not a struct (value), everything works fine.
The code:
sealed class MainViewModel : ViewModelNavigator
{
internal class HeaderButton
{
public string Content { get; set; }
public BitmapImage Icon { get; set; }
public PageContainerFactory.ContainerType ContainerType { get; set; }
public bool IsSelected { get; set; }
}
...
private List<HeaderButton> _headerButtons;
public List<HeaderButton> HeaderButtons
{
get
{
if (_headerButtons == null)
_headerButtons = new List<HeaderButton>();
return _headerButtons;
}
set { _headerButtons = value; }
}
...
HeaderButtons.First(x => x.ContainerType == CurrentContainer.CType).IsSelected = true;
The compiler is saving you from shooting yourself in the foot.
Because HeaderButton is a struct it is passed by value instead of by reference. Which means that the Linq First operator is acting on (and will return) a value copy of the element in the list.
Because the return value from First is not assigned to anything it is temporary and will go out of scope at the end of the statement, and what's more since it is a value copy and not a reference to the item in the list any changes you make to it will not affect the item in the list anyway.
If this were to compile you might easily be misled to thinking that you had updated the item in the list, which you would not have. By refusing to compile the compiler is saving you from having to track down what could be a tricky bug to find.
If you have reason to keep HeaderButton as a struct then a statement like this will enable you to update it.
var hb = HeaderButtons.First(x => x.containerType == CurrentContainer.CType);
HeaderButtons[HeaderButtons.IndexOf(hb)].IsSelected = true;
If you go this route you need to ensure your struct's equality operations behave in a way that is useful to you, which hinges on the same factors as 'If you have reason to keep HeaderButton as a struct' because part of wanting to use a struct instead of a class means wanting value equality instead of reference equality semantics.

Entity Framework C# convert int to bool

I'm attempting to re-write a VB.NET WebForms application in C# MVC. I'm having an issue with one of the properties when using Entity Framework to instantiate a class.
I have a column in my database "VATInclusive", which is of type 'int'. The original application implicitly converted a "1" or "0" to "true" or "false", but when trying to do this in my application, I get the following error:
The 'VATInclusive' property on 'Shop' could not be set to a
'System.Int32' value. You must set this property to a non-null value
of type 'System.Boolean'.
I can't simply change the type in the database as other applications make use of the table. I've tried using the following code to convert the value, but it seems to only return false, regardless of whether the database has a "0" or a "1"... Can anybody suggest a solution to this?
[Column("VATInclusive")]
private int _VATInclusive { get; set; }
[NotMapped]
public bool VATInclusive
{
get
{
if (_VATInclusive == 0)
{
return false;
}
else
{
return true;
}
}
set
{
if(_VATInclusive == 0)
{
this.VATInclusive = false;
}
else
{
this.VATInclusive = true;
}
}
}
Following some advice from the answers provided, I have rectified the issue. The issue lay with the setter accessor and also with the _VATIncusive property. By changing the code to the following I have managed to get the system to work as I expected.
However, I feel that this isn't the best approach, but it appears to be working correctly...
EDIT : EDIT : I've reduced the get accessor as per advice from Ryan and hvd..
EDIT : I'm not sure of the implications of having both properties set to public. But I don't think this is going to be an issue.
[Column("VATInclusive")]
public int _VATInclusive { get; set; }
[NotMapped]
public bool VATInclusive
{
get
{
return _VATInclusive != 0;
}
set
{
_VATInclusive = value ? 1 : 0;
}
}
If you store the column as a bit, Entity Framework automatically queries it as a Boolean for you.
You can't have a setter accessor assign to itself - this will always result in a StackOverflowException. In the below code:
set
{
if(_VATInclusive == 0)
{
this.VATInclusive = false;
}
else
{
this.VATInclusive = true;
}
}
every time this.VATInclusive is assigned to, the control flow returns to the beginning of the set accessor. This obviously can never complete.
You have some typos on your setter. I think you mean for it to be:
set
{
if(value == false)
{
_VATInclusive = 0;
}
else
{
_VATInclusive = 1;
}
}
Basically, "value" represents the bool value passed in to your setter (to be converted in to an integer). _VATInclusive is the actual object that you want to be modifying under-the-hood.
In your set, you need to compare against value:
if (value == 0)

Categories

Resources