I have a class that I wrote that contains different methods that perform calculations on data pulled from my database. Each method pulls information from the database and performs calculations on it and then saves it to a variable in the class that I can access when I initialize the class. I have two pseudo code methods below and I'm trying to figure out the following:
This is what I do when I initialize the class
public class Calculations
{
public string Symbol { get; set; }
public string Market { get; set; }
public List<decimal> stockPctReturns { get; set; }
public List<decimal> marketPctReturns { get; set; }
public enum returnType { Market, Stock };
public decimal avgAnnualMarketGrowth { get; set; }
public List<decimal> stockPctGains { get; set; }
public List<decimal> stockPctLosses { get; set; }
public List<decimal> positiveMoneyFlow { get; set; }
public List<decimal> negativeMoneyFlow { get; set; }
public decimal rsi { get; set; }
public decimal mfi { get; set; }
public decimal williamsR { get; set; }
public decimal sma20 { get; set; }
public decimal sma50 { get; set; }
public decimal sma200 { get; set; }
public const decimal riskFree10Yr = 2.58M;
public Calculations(string symbol, string market)
{
// initialize everything in the class
Symbol = symbol;
Market = market;
}
}
Do it this way:
public void fillPctReturns()
{
stockPctReturns = new List<decimal>();
marketPctReturns = new List<decimal>();
using (DailyGlobalDataTableAdapter dailyGlobalAdapter = new DailyGlobalDataTableAdapter())
using (DailyAmexDataTableAdapter dailyAmexAdapter = new DailyAmexDataTableAdapter())
using (DailyGlobalDataTable dailyGlobalTable = new DailyGlobalDataTable())
using (DailyAmexDataDataTable dailyAmexTable = new DailyAmexDataDataTable())
{
dailyAmexAdapter.Fill(dailyAmexTable);
dailyGlobalAdapter.Fill(dailyGlobalTable);
var amexQuery = from c in dailyGlobalTable.AsEnumerable()
where c.Date >= DateTime.Now.Subtract(TimeSpan.FromDays(60))
orderby c.Date descending
join d in dailyAmexTable.AsEnumerable() on c.Date equals d.Date
select new StockMarketCompare { stockClose = d.AdjustedClose, marketClose = c.AdjustedClose };
List<StockMarketCompare> amexResult = amexQuery.ToList();
// perform calculations here and save to stockPctReturns and marketPctReturns
}
}
Or should I do it this way:
using (DailyGlobalDataTableAdapter dailyGlobalAdapter = new DailyGlobalDataTableAdapter())
using (DailyAmexDataTableAdapter dailyAmexAdapter = new DailyAmexDataTableAdapter())
{
Calculations calc = new Calculations();
calc.Symbol = "GOOG";
calc.Market = "nyse";
dailyAmexAdapter.Fill(calc.dailyAmexTable);
dailyGlobalAdapter.Fill(calc.dailyGlobalTable);
calc.fillPctReturns();
}
// this example would have public properties in the calculations class for the datatables and as you can see I set them like the above
Hopefully you can tell what I'm trying to do.
It looks like the second method you show does now allow you to wrap dailyAmexTable
and dailyGlobalTable
in using blocks, so if their respective classes implement IDisposable
(which I assume they do based on your other code), then I would prefer the first method. This allows you to wrap all of your IDisposable
instances in using blocks, which you should be doing.
The main thing with using blocks is that you generally want to close them as soon as you don't need them anymore in order to free up resources. As such, you should try to do your calculations outside the using block, unless you need to save something back to the database after performing calculations. So it would look something like this:
public void fillPctReturns()
{
stockPctReturns = new List<decimal>();
marketPctReturns = new List<decimal>();
// Declare amexResult here so it is accessible outside the using block
List<StockMarketCompare> amexResult;
using (DailyGlobalDataTableAdapter dailyGlobalAdapter = new DailyGlobalDataTableAdapter())
using (DailyAmexDataTableAdapter dailyAmexAdapter = new DailyAmexDataTableAdapter())
using (DailyGlobalDataTable dailyGlobalTable = new DailyGlobalDataTable())
using (DailyAmexDataDataTable dailyAmexTable = new DailyAmexDataDataTable())
{
dailyAmexAdapter.Fill(dailyAmexTable);
dailyGlobalAdapter.Fill(dailyGlobalTable);
var amexQuery = from c in dailyGlobalTable.AsEnumerable()
where c.Date >= DateTime.Now.Subtract(TimeSpan.FromDays(60))
orderby c.Date descending
join d in dailyAmexTable.AsEnumerable() on c.Date equals d.Date
select new StockMarketCompare { stockClose = d.AdjustedClose, marketClose = c.AdjustedClose };
amexResult = amexQuery.ToList();
}
// perform calculations here and save to stockPctReturns and marketPctReturns
}
Now that I see what you are doing more clearly, I would recommend having the using blocks outside of the class. the main reason is to make sure your code is loosely coupled, in this case meaning that the data access code is separate from the business logic (a.k.a calculations) code. One way to do this is to run your query outside of the calculations class, and pass the query result to a property in the calculations class. For example:
public class Calculations
{
public List<StockMarketCompare> Data { get; set; }
// (Other properties and methods omitted.)
}
Then in your calling function:
var calc = new Calculations();
using (DailyGlobalDataTableAdapter dailyGlobalAdapter = new DailyGlobalDataTableAdapter())
using (DailyAmexDataTableAdapter dailyAmexAdapter = new DailyAmexDataTableAdapter())
using (DailyGlobalDataTable dailyGlobalTable = new DailyGlobalDataTable())
using (DailyAmexDataDataTable dailyAmexTable = new DailyAmexDataDataTable())
{
dailyAmexAdapter.Fill(dailyAmexTable);
dailyGlobalAdapter.Fill(dailyGlobalTable);
var amexQuery = from c in dailyGlobalTable.AsEnumerable()
where c.Date >= DateTime.Now.Subtract(TimeSpan.FromDays(60))
orderby c.Date descending
join d in dailyAmexTable.AsEnumerable() on c.Date equals d.Date
select new StockMarketCompare { stockClose = d.AdjustedClose, marketClose = c.AdjustedClose };
calc.Data = amexQuery.ToList();
calc.fillPctReturns();
// Run any other calculations here.
// Save data to DB here.
}