Empty data on List in LinQ Statement - c#

I got this LinQ statement
var daysList = new List<int>(new int[30]);
var model_pdv = db_pdv.Pdv.GroupBy(x => new { Pdv = x.Clave_PDV, Nombre_Pdv = x.Nombre_Pdv})
.Select(x => new DishVM()
{
Clave_PDV = x.Key.Pdv,
Nombre_Pdv = x.Key.Nombre_Pdv,
Days = daysList,
Data = x
}).ToList();
However i dont know why my "Data" List inside my LinQ gets empty values the first time but then i saves the LinQ as it should
This is my DishVm Class:
public class DishVM
{
public string Clave_PDV { get; set; }
public string Nombre_Pdv { get; set; }
public IEnumerable<Pdv> Data { get; set; }
}
And my Pdv class:
public class Pdv
{
public string Clave_PDV { get; set; }
public string Nombre_Pdv { get; set; }
}
How can i avoid the empty Data List?

The type of x within your Select statement is IGrouping, change it to produce a list:
var model_pdv = db_pdv.Pdv.GroupBy(x => new { Pdv = x.Clave_PDV, Nombre_Pdv = x.Nombre_Pdv})
.Select(x => new DishVM()
{
Clave_PDV = x.Key.Pdv,
Nombre_Pdv = x.Key.Nombre_Pdv,
Days = daysList,
Data = x.ToList()
}).ToList();

Related

Map one class data to another class with iteration

I have a C# project and looking for simple solution for map one class object data to list of another class object.
This is my input class
public class RatesInput
{
public string Type1 { get; set; }
public string Break1 { get; set; }
public string Basic1 { get; set; }
public string Rate1 { get; set; }
public string Type2 { get; set; }
public string Break2 { get; set; }
public string Basic2 { get; set; }
public string Rate2 { get; set; }
public string Type3 { get; set; }
public string Break3 { get; set; }
public string Basic3 { get; set; }
public string Rate3 { get; set; }
}
This is my another class structure
public class RateDetail
{
public string RateType { get; set; }
public decimal Break { get; set; }
public decimal Basic { get; set; }
public decimal Rate { get; set; }
}
it has a object like below. (For easiering the understanding, I use hardcoded values and actually values assign from a csv file)
RatesInput objInput = new RatesInput();
objInput.Type1 = "T";
objInput.Break1 = 100;
objInput.Basic1 = 50;
objInput.Rate1 = 0.08;
objInput.Type2 = "T";
objInput.Break2 = 200;
objInput.Basic2 = 50;
objInput.Rate2 = 0.07;
objInput.Type3 = "T";
objInput.Break3 = 500;
objInput.Basic3 = 50;
objInput.Rate3 = 0.06;
Then I need to assign values to "RateDetail" list object like below.
List<RateDetail> lstDetails = new List<RateDetail>();
//START Looping using foreach or any looping mechanism
RateDetail obj = new RateDetail();
obj.RateType = //first iteration this should be assigned objInput.Type1, 2nd iteration objInput.Type2 etc....
obj.Break = //first iteration this should be assigned objInput.Break1 , 2nd iteration objInput.Break2 etc....
obj.Basic = //first iteration this should be assigned objInput.Basic1 , 2nd iteration objInput.Basic2 etc....
obj.Rate = //first iteration this should be assigned objInput.Rate1, 2nd iteration objInput.Rate2 etc....
lstDetails.Add(obj); //Add obj to the list
//END looping
Is there any way to convert "RatesInput" class data to "RateDetail" class like above method in C#? If yes, how to iterate data set?
Try this:
public class RatesList : IEnumerable<RateDetail>
{
public RatesList(IEnumerable<RatesInput> ratesInputList)
{
RatesInputList = ratesInputList;
}
private readonly IEnumerable<RatesInput> RatesInputList;
public IEnumerator<RateDetail> GetEnumerator()
{
foreach (var ratesInput in RatesInputList)
{
yield return new RateDetail
{
RateType = ratesInput.Type1,
Break = Convert.ToDecimal(ratesInput.Break1, new CultureInfo("en-US")),
Basic = Convert.ToDecimal(ratesInput.Basic1, new CultureInfo("en-US")),
Rate = Convert.ToDecimal(ratesInput.Rate1, new CultureInfo("en-US"))
};
yield return new RateDetail
{
RateType = ratesInput.Type2,
Break = Convert.ToDecimal(ratesInput.Break2),
Basic = Convert.ToDecimal(ratesInput.Basic2),
Rate = Convert.ToDecimal(ratesInput.Rate2, new CultureInfo("en-US"))
};
yield return new RateDetail
{
RateType = ratesInput.Type3,
Break = Convert.ToDecimal(ratesInput.Break3),
Basic = Convert.ToDecimal(ratesInput.Basic3),
Rate = Convert.ToDecimal(ratesInput.Rate3, new CultureInfo("en-US"))
};
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
And use:
var list = new RatesList(new List<RatesInput>() { objInput });
foreach (var item in list)
{
Console.WriteLine(item.Basic);
}
You can use Reflection to get the properties info like this:
var props = objInput.GetType().GetProperties();
var types = props.Where(x => x.Name.StartsWith("Type"))
.Select(x => x.GetValue(objInput)).ToList();
var breaks = props.Where(x => x.Name.StartsWith("Break"))
.Select(x => x.GetValue(objInput)).ToList();
var basics = props.Where(x => x.Name.StartsWith("Basic"))
.Select(x => x.GetValue(objInput)).ToList();
var rates = props.Where(x => x.Name.StartsWith("Rate"))
.Select(x => x.GetValue(objInput)).ToList();
List<RateDetail> lstDetails = new List<RateDetail>();
for (int i = 0; i < types.Count; i++)
{
lstDetails.Add(new RateDetail
{
RateType = types[i].ToString(),
Break = Convert.ToDecimal(breaks[i]),
Basic = Convert.ToDecimal(basics[i]),
Rate = Convert.ToDecimal(rates[i])
});
}

Adding data from one list to another using linq

I need to populate a dropdown in my UI and hence added List object to the view model in my c# application. I am fetching the data in my controller code for the dropdown. What's the best way to assign data to the viewmodel object. Is linq an option?
I basically need to assign fundclasses to fundTrackRecord.FundClass
The main Viewmodel:
public class FundPerformanceVM
{
public FundPerformanceVM()
{
TrackRecord = new List<TrackRecordVM>();
}
public int FundId { get; set; }
public string FundName { get; set; }
public List<FundClassVM> FundClass { get; set; }
public string BenchmarkName1 { get; set; }
public string BenchmarkName2 { get; set; }
public List<TrackRecordVM> TrackRecord { get; set; }
public List<Tuple<string, string, string>> FundStatistics { get; set; }
}
public class FundClassVM
{
public int FundClassId { get; set; }
public string FundClass { get; set; }
}
Controller code:
var service = GetViewService<V_LEGAL_FUND_CLASS_SUMMARY>();
foreach (KeyValuePair<int, IEnumerable<FUND_PERFORMANCE>> entry in allPerformance)
{
var fundClasses = service.GetAll().Where(x => x.FUND_ID == entry.Key).Select(x => new { x.LEGAL_FUND_CLASS_ID, x.LEGAL_FUND_CLASS}).ToList();
var fundTrackRecord = new FundPerformanceVM();
fundTrackRecord.FundClass = ??;
If I understood correctly the structure of your model, you can try this:
fundTrackRecord.FundClass = fundClasses.Select(fc => new FundClassVM
{
FundClassId = fc.LEGAL_FUND_CLASS_ID,
FundClass = fc.LEGAL_FUND_CLASS
}).ToList();
You can also do this directly, replacing the code:
var fundClasses = service.GetAll().Where(x => x.FUND_ID == entry.Key).Select(x => new { x.LEGAL_FUND_CLASS_ID, x.LEGAL_FUND_CLASS}).ToList();
var fundTrackRecord = new FundPerformanceVM();
With:
var fundTrackRecord = new FundPerformanceVM();
fundTrackRecord.FundClass = service.GetAll().
Where(x => x.FUND_ID == entry.Key).
Select(fc => new FundClassVM
{
FundClassId = fc.LEGAL_FUND_CLASS_ID,
FundClass = fc.LEGAL_FUND_CLASS
}).ToList();

Get selected column from iqueryable

How can I return fieldList from an IQueryable object?
// fieldList="Code,Name";
var result = from Activity in query
select new
{
Code = Activity.Code,
Name = Activity.Name,
StatusCode = Activity.ClaimStatus.Name
};
DTO
public class CustomDto
{
public string Code { get; set; }
public string Name { get; set; }
public string StatusCode { get; set; }
}
Convert To Dto
var result = items.AsQueryable().Select(x => new CustomDto()
{
Code = x.Code,
Name = x.Name,
StatusCode = x.ClaimStatus
}).ToList();

How do I use LINQ to group & project objects, based on a member dictionary key?

I have a List<Predictions> that I would like to project onto a List<List<PredictionObj>>. These two classes are defined as follows:
public Predictions
{
public Dictionary<string, double> PredictedMetrics { get; private set; }
public DateTime PredictionTimeStamp { get; set; }
public Predictions()
{
PredictedMetrics = new Dictionary<string, double>();
}
}
public class PredictionObj
{
public string PredictedMetricName { get; set; }
public double PredictedMetricValue { get; set; }
public DateTime PredictionTimeStamp { get; set; }
}
For context, each Predictions object in the List<Predictions> list contains a collection (PredictedMetrics) of predicted values for a set of metrics, which were made at PredictionTimeStamp. I'd like to separate each of those metrics into their own list, such that there will be one list (List<PredictionObj>) for every unique PredictedMetrics key in the list. (PredictedMetricName will map to the dictionary's key, PredictedMetricValue will map to the dictionary's value). I'd like to store all of these lists in one List<List<PredictionObj>> list.
Is there a way to accomplish this using LINQ extension methods?
You can copy/paste the source below into LINQPad as an example. I'm looking for LINQ that will accomplish what GenerateSeperateMetricLists is doing:
void Main()
{
DateTime currTime = DateTime.UtcNow;
List<Predictions> records = new List<Predictions>();
Predictions record1 = new Predictions();
record1.PredictedMetrics.Add("metric1", 2.2d);
record1.PredictedMetrics.Add("metric2", 0.2d);
record1.PredictionTimeStamp = currTime;
records.Add(record1);
Predictions record2 = new Predictions();
record2.PredictedMetrics.Add("metric1", 1.2d);
record2.PredictedMetrics.Add("metric2", 0.1d);
record2.PredictionTimeStamp = currTime.AddMinutes(1);
records.Add(record2);
Predictions record3 = new Predictions();
record3.PredictedMetrics.Add("metric1", 3.2d);
record3.PredictedMetrics.Add("metric2", 0.3d);
record3.PredictionTimeStamp = currTime.AddMinutes(2);
records.Add(record3);
Predictions record4 = new Predictions();
record4.PredictedMetrics.Add("metric1", 4.2d);
record4.PredictedMetrics.Add("metric2", 0.4d);
record4.PredictionTimeStamp = currTime.AddMinutes(3);
records.Add(record4);
//What's the LINQ that could replace this method?
GenerateSeperateMetricLists(records).Dump();
}
private static List<List<PredictionObj>> GenerateSeperateMetricLists(List<Predictions> predictionRecords)
{
var predictionMetricLists = new List<List<PredictionObj>>();
foreach (Predictions forecastRecord in predictionRecords)
{
foreach (KeyValuePair<string, double> prediction in forecastRecord.PredictedMetrics)
{
PredictionObj predictionMetric = new PredictionObj
{
PredictedMetricName = prediction.Key,
PredictedMetricValue = prediction.Value,
PredictionTimeStamp = forecastRecord.PredictionTimeStamp
};
var metricList = predictionMetricLists.Where(x => x.First().PredictedMetricName == prediction.Key);
if (metricList.Count() == 0)
{
predictionMetricLists.Add(new List<PredictionObj> {predictionMetric});
}
else
{
metricList.First().Add(predictionMetric);
}
}
}
return predictionMetricLists;
}
private class Predictions
{
public Dictionary<string, double> PredictedMetrics { get; private set; }
public DateTime PredictionTimeStamp { get; set; }
public Predictions()
{
PredictedMetrics = new Dictionary<string, double>();
}
}
private class PredictionObj
{
public string PredictedMetricName { get; set; }
public double PredictedMetricValue { get; set; }
public DateTime PredictionTimeStamp { get; set; }
}
You should first flatten the data into a list of PredictionObj:
var flatList = records
.SelectMany(r => r.PredictedMetrics.Select(p => new PredictionObj
{
PredictedMetricName = p.Key,
PredictedMetricValue = p.Value,
PredictionTimeStamp = r.PredictionTimeStamp
}));
This produces a flat sequence of PredictionObj objects. Now you can group them by PredictedMetricName:
flatList.GroupBy(x => x.PredictedMetricName).Dump();
The query syntax equivalent, in one statement:
(
from r in records
from p in r.PredictedMetrics
select new PredictionObj
{
PredictedMetricName = p.Key,
PredictedMetricValue = p.Value,
PredictionTimeStamp = r.PredictionTimeStamp
} into flatList
group flatList by flatList.PredictedMetricName into fg
select fg
).Dump();
You just need to take each Prediction and project it into a List<PredictionObj> and then convert those into a List<Prediction>:
var ans = records.SelectMany(p => p.PredictedMetrics.Select(pm => new PredictionObj { PredictedMetricName = pm.Key, PredictedMetricValue = pm.Value, PredictionTimeStamp = p.PredictionTimeStamp }))
.GroupBy(p => p.PredictedMetricName)
.Select(g => g.ToList())
.ToList();
Updated for change in OP.

return multiple reader.cast<>

All I want to do is return multiple reader.cast<> so that i can use 2 sqlcommands.
var first =reader.Cast<IDataRecord>().Select(x => new LocationInfo()
{
Names = x.GetString(0),
Values = Math.Round(x.GetDouble(1), 2).ToString("#,##0.00"),
ValuesDouble = x.GetDouble(1)
}).ToList();
reader.NextResult();
var second=reader.Cast<IDataRecord>().Select(x => new LocationInfo()
{
Names2 = x.GetString(0),
Values2 = Math.Round(x.GetDouble(1), 2).ToString("#,##0.00"),
ValuesDouble2 = x.GetDouble(1)
}).ToList();
All I want to do is return var first and var second. Please help :(
I'm using this Location.cs for parameters:
namespace MVCRealtime
{
public class LocationInfo
{
public string Names { get; set; }
public string Values { get; set; }
public double ValuesDouble { get; set; }
public string Names2 { get; set; }
public string Values2 { get; set; }
public double ValuesDouble2 { get; set; }
}
}
public static class ReaderHelper
{
public static IEnumerable<TElem> GetData<TElem>(this IDataReader reader, Func<IDataRecord, TElem> buildObjectDelegat)
{
while (reader.Read())
{
yield return buildObjectDelegat(reader);
}
}
}
// ...
var result = reader.GetData(x => new LocationInfo()
{
Names = x.GetString(0),
Values = Math.Round(x.GetDouble(1), 2).ToString("#,##0.00"),
ValuesDouble = x.GetDouble(1)
}).Take(2);
So you get 1st var in 1st element of the result and 2nd var in 2nd element.

Categories

Resources