Calculate years in a POCO Calculated Property - c#

I'm assuming I'm pretty close. I have a value StartedAgent that will contain a specific date entered by the user. Lets say they entered "1/1/1985" I then want to create a calculated property that I can use to display how many years since this agent first started working in Real Estate. Below is my class. I have tried to take a stab at it, but I'm coming up short. I'm using MVC 5, EF 6 & .Net 4.5 in the flavor of C#.
namespace OrlandoAppraiser.Models
{
public class Appraiser
{
public int AgentID { get; set; }
public string Name { get; set; }
public string LicenseNum { get; set; }
public DateTime StartedAgent { get; set; }
public string YearsAsAgent
{
get { return (Math.Floor((DateTime.Now - StartedRealEstate).TotalDays / 365.25D)); }
}
}
}
I have looked at some different answers, but I'm having trouble finding a way of doing this simple inside a calculated property. I know it shouldn't be that much different, but I'm getting errors with my code.

This is a pretty simplistic approach. Make sure you call ToString() if the property is a string.
public string YearsAsAgent
{
get { return (DateTime.Now.Year - StartedRealEstate.Year).ToString(); }
}

This should help. Modified version of this.
DateTime _startedRealEstate = new DateTime(2012, 11, 15);
public DateTime StartedRealEstate { get { return _startedRealEstate; } set { _startedRealEstate = value; } }
public int YearsAsAgent
{
get
{
DateTime zeroTime = new DateTime(1, 1, 1);
TimeSpan span = DateTime.Now - StartedRealEstate;
int years = (zeroTime + span).Year - 1;
return years;
}
}
private void button1_Click_2(object sender, EventArgs e)
{
int totalYears = YearsAsAgent;
}

Related

C# Removing data from a list

So I have recently started working with C# and now I got a project to do at home...
I have a situation where I have a data file with information about an undefined amount of rings.... Their Maker, Name, Metal, Weight, Size, Purity and Price.
I've read the file... and separated the rings into a class which looks like:
class Rings
{
public string Maker { set; get; }
public string Name { set; get; }
public string Metal { set; get; }
public string Weight { set; get; }
public string Size { set; get; }
public string Purity { set; get; }
public string Price { set; get; }
public Rings() { }
public Rings(string maker, string name, string metal, string weight, string size, string purity, string price)
{
Maker = maker;
Name = name;
Metal = metal;
Weight = weight;
Size = size;
Purity = purity;
Price = price;
}
}
Now the final part of the project is to find and print to a file rings, which are under 300 in price and are either size 13 or 14... So I came up with the idea to make a loop and a couple of if functions to delete all rings which do not suit these requirements from the list, and then simply print out what's left of the list...
Here's the method:
public static void SpecificRings(List<Rings> RingList)
{
foreach(var x in RingList)
{
int ThePrice = int.Parse(x.Price);
int TheSize = int.Parse(x.Size);
if (ThePrice >= 300)
{
RingList.Remove(x);
}
else if (TheSize != 12 || TheSize != 13)
{
RingList.Remove(x);
}
}
}
Now the problem is that I do not know how to remove the actual things from the list... I understand that I'll need to make 7 of the RingList.Remove(); But how do I specify which information to delete? Any questions are welcome if I didn't explain the situation well enough
First, change the types of properties on Rings to what they actually represent. That way you can do comparisons on the data (say, rings weighing more than 10 grams and worth less than $100).
class Rings
{
public string Maker { set; get; }
public string Name { set; get; }
public string Metal { set; get; }
public double Weight { set; get; }
public float Size { set; get; }
public string Purity { set; get; } //I don't know what this is... An int?
public decimal Price { set; get; }
public Rings() { }
public Rings(string maker, string name, string metal, double weight, float size, string purity, decimal price)
{
Maker = maker;
Name = name;
Metal = metal;
Weight = weight;
Size = size;
Purity = purity;
Price = price;
}
}
Secondly, don't remove them from the list. Just return a new list with the rings you're looking for. What if you want to find a specific set of rings, then you decide you want a slightly different filter applied? Don't re-read the list, just re-use it:
public static IEnumerable<Rings> FilterRings(IEnumerable<Rings> RingList, decimal price, string maker /* etc.......*/)
{
return ringList.Where(r => r.Price <= price /* or > or == or whatever*/)
.Where(r => r.Maker == maker);
//.Where etc.. etc...
}
You don't even really need the function above. Just call the Linq method directly with what you're looking for.
You're going to run into trouble here. Just to start with, you can't remove an item from a collection while you're enumerating the collection in a foreach loop.
foreach(var x in RingList)
{
int ThePrice = int.Parse(x.Price);
int TheSize = int.Parse(x.Size);
if (ThePrice >= 300)
{
// >>> Exception will be throw on next line
RingList.Remove(x);
The second proplem is that you've got one list of Rings, and you're removing items from it. Then they're gone. That can cause confusion.
There's a third problem:
if (TheSize != 12 || TheSize != 13)
That's not going to work well. Every ring is either not size 12, or not size 13. If it's 13, it's not 12; if it's 12, it's not 13. That line will discard everything.
I think you mean you want to keep only size 12 and size 13 rings, but that's a guess. Maybe you want to discard only size 12 and size 13? Let me know.
Here's a very simplified version of the function I would write to do what you're doing in SpecificRings. You say you're at a very early stage of learning, so I'll try to stick with stuff you've probably seen already.
First, if a function is getting specific rings, call it GetSpecificRings(). The compiler doesn't care, but it makes it easier to keep track of what your code is doing in your own mind.
But first, let's not use strings for everything:
class Rings
{
public string Maker { set; get; }
public string Name { set; get; }
public string Metal { set; get; }
// All these should be numbers
public decimal Weight { set; get; }
public decimal Size { set; get; }
public decimal Purity { set; get; }
public decimal Price { set; get; }
And now to get our specific rings:
public List<Rings> GetSpecificRings(List<Rings> rings)
{
var rtn = new List<Rings>();
foreach (var r in rings)
{
if (r.Price < 300 && (r.Size == 12 || r.Size == 13))
{
rtn.Add(r);
}
}
return rtn;
}
Then you can call that function to get that subset of rings:
var myAffordableRingsInSomeSizes = GetSpecificRings(RingList);
I assume you're getting RingList from somewhere, like a database, or just statically initializing it. We can go into that further if we need to.
Here's another way to do the same thing, using stuff you may not have learned yet:
var sameResults = RingList.Where(r =>
r.Price < 300 && (r.Size == 12 || r.Size == 13))
).ToList();
Take your pick.

Storing/retrieving a JSON string in the database making it easy to work with in code

I have a c# object 'Product' with a property called: Offset
In the database the field is of type nvarchar(50)
I will be storing a JSON value in it such as the following: { "y": 0, "m": 0, "d": 0 }
I would like to know a good way of working with a property like this in my code. Here is how I currently am doing it:
public class Product
{
public int Id {get; set;}
public string Description {get; set;}
public decimal Price {get; set;}
public int OffsetYears { get; set; }
public int OffsetMonths { get; set; }
public int OffsetDays { get; set; }
public string Offset
{
get
{
Offset offset = new Offset()
{
Y = OffsetYears,
M = OffsetMonths,
D = OffsetDays
};
return JsonConvert.SerializeObject(offset);
}
set
{
OffsetObj offset = JsonConvert.DeserializeObject<Offset>(value);
OffsetYears = offset.Y;
OffsetMonths = offset.M;
OffsetDays = offset.D;
}
}
private class OffsetObj
{
public int Y { get; set; }
public int M { get; set; }
public int D { get; set; }
}
}
So then when I accept values from the User in the UI I would set the OffsetYears, OffsetMonths, and OffsetDays properties.. So in my repository I can just save Offset.
And when retrieving values from the database I will simply work with OffsetYears, OffsetMonths, and OffsetDays properties in my code.
Is there a better way to handle this sort of thing? I just feel like I am not utilizing all of my c# resources. Like what if another developer accidentally sets Offset through the code assuming any format of string can go in it.
Or am I better off just creating 3 separate integer fields in the database and avoiding all of this...
I would hold the values in a field of your private type. Consider this approach:
public class Product
{
private OffsetObj _offset = new OffsetObj();
public int Id { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int OffsetYears
{
get { return _offset.Y; }
set { _offset.Y = value; }
}
public int OffsetMonths
{
get { return _offset.M; }
set { _offset.M = value; }
}
public int OffsetDays
{
get { return _offset.D; }
set { _offset.D = value; }
}
public string Offset
{
get
{
return JsonConvert.SerializeObject(_offset);
}
set
{
_offset = JsonConvert.DeserializeObject<OffsetObj>(value);
}
}
private class OffsetObj
{
public int Y { get; set; }
public int M { get; set; }
public int D { get; set; }
}
}
This way, the field offset will hold the values for the offset.
Like what if another developer accidentally sets Offset through the code assuming any format of string can go in it.
JsonConvert will throw a JsonReaderException if trying to set the Offset property to a string that does not match JSON-format. In my opinion this is expected. To clarify further, you could name your property to OffsetJson.
However, I fail to see the benefit in this simple case to store your information as JSON. If you are using a relational database, you may as well just store your values in separate columns.

Class List Keeps Printing Out As Class Name In Console?

Ok, so maybe I'm just tired or something but I can't seem to figure out why this keeps happening.
The code below is called every day for a data point in a database I have.
When I print to the console for debugging, it simply prints out as:
NamespaceName.SharePrices
Not sure what is going on.
public void OnData(TradeBars data)
{
decimal price = data["IBM"].Price;
DateTime today = data["IBM"].Time;
//--------------Below works fine.
if (today.Date >= nextTradeDate.Date)
{
MarketOnOpenOrder("IBM", 50);
Debug("Purchased Stock");
nextTradeDate = today.AddDays(1);
MarketOnOpenOrder("IBM", -25);
}
var derpList = new SharePrices { theDate = today, sharePrice = price };
List<SharePrices> newList = new List<SharePrices>();
newList.Add(derpList);
newList.ForEach(Console.WriteLine);
}
}
public class SharePrices
{
public DateTime theDate { get; set; }
public decimal sharePrice { get; set; }
}
Please excuse my naming conventions. This is just a wireframe for a personal project.
//----------Edit
Thanks for the help guys. I guess what I wasn't understanding is why it was working in my TestClass I wrote just playing with fake data, and when the real implementation came it didn't work:
public static void FindWindowDays()
{
DateTime currentDate = DateTime.Now;
var dates = new List<DateTime>();
for (var dt = currentDate.AddDays(-windowDays); dt <= currentDate; dt = dt.AddDays(1))
{
dates.Add(dt);
}
var ascending = dates.OrderByDescending(i => i);
foreach (var datesyo in ascending)
{
Console.WriteLine(datesyo);
}
}
This seemed to work fine printing the DateTime to console without converting to string. But when I added the second element, it stopped working. That's where I got confuddled.
C# doesn't know anything about the SharePrices other than the class name. If you want it to display something specific, you will need to override the ToString() method like so:
public override string ToString()
{
return "SharePrice: " + theDate.ToString() + ": " + sharePrice.ToString();
}
Of course, you can format it however you like, that is the beauty of it. If you only care about the price and not the date, only return the sharePrice.
You should override ToString() for your class in format as you want, for example like this:
public class SharePrices
{
public DateTime theDate { get; set; }
public decimal sharePrice { get; set; }
public override string ToString()
{
return String.Format("The Date: {0}; Share Price: {1};", theDate, sharePrice);
}
}
By default, without overriding, ToString() returns a string that represents the current object. So that's why you get what you described.
When you call Console.WriteLine on a class, it will call the ToString() method on that class automatically.
If you want to print the details out, you will over need to override ToString() in your class, or call Console.WriteLine with each property you want to print out.
this will work without having to use .ToString()
public class SharePrices
{
public DateTime theDate { get; set; }
public decimal sharePrice { get; set; }
}
SharePrices sp = new SharePrices() { theDate = DateTime.Now, sharePrice = 10 };
var newList2 = new List<SharePrices>();
newList2.Add(sp);
newList2.ForEach(itemX => Console.WriteLine("Date: {0} Sharprice: {1}",sp.theDate, sp.sharePrice));

Switching logic on Domain Model

I'm currently developing an app using ASP.NET MVC3 and Entity Framework 4.1 Code First and also trying to apply DDD little by little since I'm only began learning it.
I have a model of :
public class ClassA
{
public decimal MonthlyRate { get; set; }
public virtual decimal DailyRate
{
get { return this.MonthlyRate / 30; }
private set { }
}
}
Right now, this code works but what if I'll be having a flag (which will be checked by user) on the View triggering for a new computation. Let's say the flag instead of dividing it by 30, monthly rate now will be divided by 5. Any suggestions? Thanks.
interface IDivideLogic
{
int DivideNumber{get;set;}
}
class DivideLogic : IDivideLogic
{
public DivideLogic()
{
DivideNumber = 30;
}
public DivideLogic(int divideNumber)
{
DivideNumber = divideNumber;
}
public int DivideNumber{get;set;}
}
public class ClassA
{
public IDivideLogic DivideLogic {get;set;}
public decimal MonthlyRate { get; set; }
public virtual decimal DailyRate
{
get { return this.MonthlyRate / DivideLogic.DivideNumber; }
private set { }
}
}
then you can switch this when you want
ClassA obj = new ClassA();
obj.DivideLogic = new DivideLogic(5);
This works well for more complicated situations. In your situation it may be too over designed. Hope you get the point
You could use a strategy pattern for this. You could use various implementations of your division logic. Assuming you want to anticipate further change this would be a good way to solve this problem. This way you abstract the division logic from the other logic making it easy to implement different implementations of the division logic.
You can declare the value as a property and assign it from UI.
public class ClassA
{
public decimal MonthlyRate { get; set; }
public int YourProperty {get; set;}
public ClassA(int yourProperty)
{
YourProperty = yourProperty;
}
public virtual decimal DailyRate
{
get { return this.MonthlyRate / YourProperty; }
private set { }
}
}

LINQ - Set element in Dictionary to empty where DateTime value is oldest

I have a Dictionary<string, XMLMessage> where XMLMessage is a struct:
private struct XMLMessage
{
public string Message { get; set; }
public DateTime TimeRead { get; set; }
}
I will use the Dictionary similar to this:
storedMessages["1X"] = new XMLMessage() { Message = "<XML>1X</XML>", TimeRead = DateTime.Now };
storedMessages["1Y"] = new XMLMessage() { Message = "<XML>1Y</XML>", TimeRead = DateTime.Now };
There will be a gap in seconds between the the dictionary object assigning a value hence the DateTime object.
At some point I need to keep the keys in the Dictionary but the oldest value to be set to empty.
I have tried this but don't seem to have got it quite right.
storedMessages.Where(x => x.Key.Contains("1")).OrderBy(s => s.Value.TimeRead).Skip(1)
Thanks
UPDATE: I think I can do something like this but wanted to get your opinions
var j = storedMessages.Where(x => x.Key.Contains("1")).OrderByDescending(s => s.Value.TimeRead).First().Key;
storedMessages[j] = new XMLMessage();
Yes, your updated version looks okay - although I'd say you'd be better off storing a list in time order as well as the dictionary, to make life easier.
I would strongly discourage you from using mutable structs though. Either use a class, or change the struct to be immutable.
Example of making it a class:
private class XmlMessage
{
public string Message { get; set; }
public DateTime TimeRead { get; set; }
}
Example of making it an immutable struct:
private struct XmlMessage
{
private readonly string message;
private readonly DateTime timeRead;
public string Message { get { return message; } }
public DateTime TimeRead { get { return timeRead; } }
public XmlMessage(string message, DateTime timeRead)
{
this.message = message;
this.timeRead = timeRead;
}
}
Of course you could make it an immutable class instead...

Categories

Resources