Reputation: 501
I know that Linq cannot handle ToString()
and I've read a few work arounds, most seem to be doing the casting outside of the Linq query, but this is for the output where I am trying to shove it into a list and this is where it is blowing up.
As the code will show below I did some casting elsewhere already in order to make it fit in Linq, but the very last part has the tostring and this I need to rewrite too but I'm not sure how.
DateTime edate = DateTime.Parse(end);
DateTime sdate = DateTime.Parse(start);
var reading = (from rainfall in db.trend_data
join mid in db.measurements on rainfall.measurement_id equals mid.measurement_id
join siteid in db.sites on mid.site_id equals siteid.site_id
where siteid.site_name == insite && rainfall.trend_data_time >= sdate && rainfall.trend_data_time <= edate
select new GaugeData() { SiteID = siteid.site_name, Data_Time = rainfall.trend_data_time, Trend_Data = float.Parse(rainfall.trend_data_avg.ToString()) }).ToList();
Upvotes: 1
Views: 547
Reputation: 35018
Linq will handle it, however Linq2Entities will not since EF will want to relay that expression to the DbProvider which doesn't understand/translate all .Net methods.
When it comes to extracting data from entities, the path with the least pain is to have your entity definitions should use the compatible .Net types matching the SQL data types. Then when you want to load that data into view models / DTOs where you might want to perform formatting or data type translation, let the ViewModel/DTO handle that or pre-materialized your Linq2Entity query into an anonymous type list and then process the translations /w Linq2Object.
Without knowing the data type of your TrendDataAvg, an example with a value stored as a decimal, but you want to work with float:
Formatting in ViewModel example:
public class TrendData // Entity
{ // ...
public decimal trend_data_avg { get; set; }
// ...
}
public class GuageData // ViewModel
{
public decimal trend_data_avg { get; set; } // Raw value.
public float Trend_Data // Formatted value.
{
get { return Convert.ToSingle(trend_data_avg); }
}
}
var reading = (from rainfall in db.trend_data
join mid in db.measurements on rainfall.measurement_id equals mid.measurement_id
join siteid in db.sites on mid.site_id equals siteid.site_id
where siteid.site_name == insite && rainfall.trend_data_time >= sdate && rainfall.trend_data_time <= edate
select new GaugeData() { SiteID = siteid.site_name, Data_Time = rainfall.trend_data_time, trend_data_avg = rainfall.trend_data_avg }).ToList();
Anonymous Types Example:
public class GuageData // ViewModel
{
public float Trend_Data { get; set; }
}
var reading = (from rainfall in db.trend_data
join mid in db.measurements on rainfall.measurement_id equals mid.measurement_id
join siteid in db.sites on mid.site_id equals siteid.site_id
where siteid.site_name == insite && rainfall.trend_data_time >= sdate && rainfall.trend_data_time <= edate
select new
{
siteid.site_name,
rainfall.trend_data_time,
rainfall.trend_data_avg
}.ToList() // Materializes our Linq2Entity query to POCO anon type.
.Select( x=> new GaugeData
{
SiteID = site_name,
Data_Time = trend_data_time,
Trend_Data = Convert.ToSingle(trend_data_avg)
}).ToList();
Note: If you use the Anonymous Type method and want to utilize paging, additional filtering, etc. then be sure to do it before the initial .ToList() call so that it is processed by the Linq2EF. Otherwise you would be fetching a much larger set of data from EF than is necessary with potential performance and resource utilization issues.
Additionally, if you set up your navigation properties in your entities you can avoid all of the explicit join syntax. EF is designed to do the lifting when it comes to the relational DB, not just an alternate syntax to T-SQL.
// Given trend data has a single measurement referencing a single site.
var gaugeData = db.trend_data
.Where(x => x.trend_data_time >= sdate
&& x.trend_data_time <= edate
&& x.measurement.site.site_name == insite))
.Select(x => new
{
x.measurement.site.site_name,
x.trend_data_time,
x.trend_data_avg
}).ToList()
.Select( x=> new GaugeData
{
SiteID = site_name,
Data_Time = trend_data_time,
Trend_Data = Convert.ToSingle(trend_data_avg)
}).ToList();
Upvotes: 3
Reputation: 799
You could use the Convert.ToSingle()
method, float
is an alias for system.single
.
Trend_Data = Convert.ToSingle(rainfall.trend_data_avg)
Upvotes: 0