Max value LINQ using class - linq

I've got this class
public class Materiale
{
public string IdMateriale { get; set; }
public string GenereMateriale { get; set; }
public string Categoria { get; set; }
public string Modello { get; set; }
public string Tipo { get; set; }
public string NumSerie { get; set; }
public int Anno { get; set; }
public string DittaCostruttrice { get; set; }
public string Note { get; set; }
public List<Controllo> Controlli = new List<Controllo>();
}
public class Controllo
{
public string IdControllo { get; set; }
public DateTime DataControllo { get; set; }
public string IdMateriale { get; set; }
public string Utente { get; set; }
public string Stato { get; set; }
public string Note { get; set; }
}
I want to query a list of "Materiale" filtering "Controlli". I need to retrieve all properties of the "Materiale" class and only one property of the "Controllo" class (the one named "Stato"). From the list "Controlli" I need the one that has the most recent "DataControllo" property.
I try this in a LINQ query but I receive an error (Max doesn't exist in the current context)
List<Materiale> m = new List<Materiale>();
List<Materiale> m2 = (from ma in m
from c in ma.Controlli
where c.DataControllo == Max(c.DataControllo)
select new
{
ma, c.Stato
}).ToList();
Can someone help me

#Christos is correct, here is my version with let in query syntax:-
List<Materiale> m2 = from m in MaterialeList
let RecentControllo = m.OrderByDescending(x => x.DataControllo)
.FirstOrDefault()
select new Materiale
{
IdMateriale = m.IdMateriale,
GenereMateriale = m.GenereMateriale,
//Similarily other properties of Materiale here
Stato = RecentControllo != null ? RecentControllo.Stato : ""
}).ToList();

I think that you need something more simple like the following one:
List<Materiale> m2 = from ma in m
let mostRecentControllo = ma.Controlli
.OrderByDescending(c=>c.DataControllo)
.FirstOrDefault()
select new
{
Materiale = ma,
Stato = mostRecentControllo != null
? mostRecentControllo.Stato : null
}).ToList();
I have supposed that each Materiale's Controlli list contains Controllo with the same IdMateriale.

Related

InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List to System.Collections.Generic.IEnumerable

I am trying to implementation clean architecture in netcore and I have Runtime Error
InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List to System.Collections.Generic.IEnumerable
In the WebUI I have Match controller and ViewAllMatch Action like this
public async Task<IActionResult> ViewAllMatch()
{
var matches = await _mediator.Send(new GetMatchesDetail());
return View(matches);
}
In the application Layer I have A queries like this:
public class GetMatchesDetail : IRequest<IEnumerable<MatchesDetail>>
{
}
public class MatchesDetail
{
public string MatchId { get; set; }
public int MatchNumer { get; set; }
public DateTime DateMatch { get; set; }
public TimeSpan TimeMatch { get; set; }
public int MatchYear { get; set; }
public string SeasonId { get; set; }
public string Round { get; set; }
/// <summary>
/// Set value to Qualified for Qualified and Final for Final Round
/// </summary>
public string Stage { get; set; }
public string SubStage { get; set; }
public string HTeam { get; set; }
public string HTeamCode { get; set; } //For Flag get from Table Team from Foreign Key TeamName
public int HGoal { get; set; }
public int GGoal { get; set; }
public string GTeam { get; set; }
public string GTeamCode { get; set; }
public string WinNote { get; set; }
public string Stadium { get; set; }
public string Referee { get; set; }
public long Visistors { get; set; }
public string Status { get; set; }
}
public class GetMatchesHandler : IRequestHandler<GetMatchesDetail, IEnumerable<MatchesDetail>>
{
private readonly IMatchRepository _matchRepository;
public GetMatchesHandler(IMatchRepository matchRepository)
{
_matchRepository = matchRepository;
}
public async Task<IEnumerable<MatchesDetail>> Handle(GetMatchesDetail request, CancellationToken cancellationToken)
{
var matchlistview = await _matchRepository.GetMatchDetailAsync();
return matchlistview;
}
}
And the code for matchRepository to get all the match in Infastructure like this.
public async Task<IEnumerable<MatchesDetail>> GetMatchDetailAsync()
{
var matchDetailList = (from match in _context.Matches
join team1 in _context.Teams on match.HTeam equals team1.TeamName
join team2 in _context.Teams on match.GTeam equals team2.TeamName
join season in _context.Seasons on match.SeasonId equals season.SeasonId
select new
{
match.MatchId,
match.MatchNumber,
match.DateMatch,
match.TimeMatch,
match.MatchYear,
match.SeasonId,
season.SeasonName,
match.Round,
match.Stage,
match.SubStage,
match.HTeam,
HTeamCode = team1.TeamCode,
match.HGoal,
match.GGoal,
match.GTeam,
GTeamCode = team2.TeamCode,
match.WinNote,
match.Stadium,
match.Referee,
match.Visistors
});
return (IEnumerable<MatchesDetail>)await matchDetailList.ToListAsync();
}
Full code have been upload to Github at https://github.com/nguyentuananh921/Betting.git.
for more detail.
Thanks for your help.
I am so confuse about model in clean architech when i have more entities and the model I want to view in the WebUI contain many entities in domain.
Thanks for your help.
I have Modify public IEnumerable GetMatchDetailAsync() like that.
public IEnumerable<MatchesDetail> GetMatchDetailAsync()
{
#region TryOther way
var matchQuery = (from match in _context.Matches
join team1 in _context.Teams on match.HTeam equals team1.TeamName
join team2 in _context.Teams on match.GTeam equals team2.TeamName
join season in _context.Seasons on match.SeasonId equals season.SeasonId
select new
{
#region selectResult
//Remove to clear Select what I want to get.
#endregion
});
MatchesDetail matchesDetail = new MatchesDetail();
List<MatchesDetail> retList = new List<MatchesDetail>();
//IEnumerable<MatchesDetail> retList;
foreach (var item in matchQuery)
{
#region ManualMapping
matchesDetail.MatchId = item.MatchId;
//other field mapping
#endregion
retList.Add(matchesDetail);
}
#endregion
return retList;
}
And it work

I try to add entity model class data to my another list ,but after foreach Same rows insert in every row , MVC

This is my Entity model class which was auto generated by Ado.net model
public partial class SubModule
{
public int SubModuleId { get; set; }
public Nullable<int> ModuleId { get; set; }
public string SubModuleName { get; set; }
public Nullable<bool> Active { get; set; }
public Nullable<bool> IsModules { get; set; }
public string url { get; set; }
public string path { get; set; }
public string subform { get; set; }
}
this is my another class
public class ChildModules
{
public int ? SubModuleId { get; set; }
public Nullable<int> ModuleId { get; set; }
public string SubModuleName { get; set; }
public Nullable<bool> Active { get; set; }
public Nullable<bool> IsModules { get; set; }
public string url { get; set; }
public string path { get; set; }
public string subform { get; set; }
}
I want to copy Sub modules data to my Child modules class properties
My code is
List<SubModule> ChildModule = entity.SubModules.Where(x => x.IsModules == false).ToList();
List<ChildModules> listchildmodules = new List<ChildModules>();
ChildModules chmodule = new ChildModules();
foreach (SubModule mod in ChildModule)
{
chmodule.SubModuleId = mod.SubModuleId;
chmodule.ModuleId = mod.ModuleId;
chmodule.SubModuleName = mod.SubModuleName;
chmodule.Active = mod.Active;
chmodule.IsModules = mod.IsModules;
chmodule.url = mod.url;
chmodule.path = mod.path;
chmodule.subform = mod.subform;
listchildmodules.Add(chmodule);
}
but in listchildmodules last row insert in every index.
Why?
Your code always add the same object always. Because you always updating the values of same object and insert that into list.
Keep the below line of code inside foreach.
ChildModules chmodule = new ChildModules();
Your foreach should look like below
foreach (SubModule mod in ChildModule)
{
ChildModules chmodule = new ChildModules();
chmodule.SubModuleId = mod.SubModuleId;
chmodule.ModuleId = mod.ModuleId;
chmodule.SubModuleName = mod.SubModuleName;
chmodule.Active = mod.Active;
chmodule.IsModules = mod.IsModules;
chmodule.url = mod.url;
chmodule.path = mod.path;
chmodule.subform = mod.subform;
listchildmodules.Add(chmodule);
}
Or you could declare ChildModules chmodule; outside foreach and initialize chmodule = new ChildModules(); inside foreach loop.

Convert query expression to lambda in LINQPad4

While coding I had came across a LINQ query that I was able to accomplish in query syntax but not in lamda syntax. While this works fine in the application, I wanted to learn the query syntax for what I was trying to do.
Essentially, I have a database with views, CO_Leather_V and CO_LeatherSizeColor_V. I also have two classes, CuttingOrder and CuttingOrderDetail. CuttingOrderDetail contains entirely string,int and float properties. The CuttingOrder Class contains 2 string properties and a List of CuttingOrderDetails.
public class CuttingOrder
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public List<CuttingOrderDetail> details { get; set; }
}
public class CuttingOrderDetail
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public string itemCode { get; set; }
public string material { get; set; }
public string color { get; set; }
public string size { get; set; }
public int qty { get; set; }
public float squareFeet { get; set; }
public float squareFeetUsed { get; set; }
}
The query expression I used to get a list of all CuttingOrders with a given SalesOrder was
cos = (from l in db.CO_Leather_Vs
where l.orderNo == Globals.orderNo
select new Globals.CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = (
from d in db.CO_LeatherSizeColor_Vs
select new Globals.CuttingOrderDetail
{
cuttingOrderNo = d.orderNo
}
).ToList()
}).ToList();
I converted this to work in LINQPad with the following query, but I can't get anything to show on the lambda pane.
void Main()
{
var p = (from l in CO_Leather_V
select new CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = (
from d in CO_LeatherSizeColor_V
select new CuttingOrderDetail
{
cuttingOrderNo = d.OrderNo
}
).ToList()
}).ToList();
p.Dump();
}
// Define other methods and classes here
public class CuttingOrder
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public List<CuttingOrderDetail> details { get; set; }
}
public class CuttingOrderDetail
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public string itemCode { get; set; }
public string material { get; set; }
public string color { get; set; }
public string size { get; set; }
public int qty { get; set; }
public float squareFeet { get; set; }
public float squareFeetUsed { get; set; }
}
If anyone knows how to perform the linq query in lambda form or knows why LINQPad is unable to generate the lamda form it would be greatly appreciated.
This should work:
var p = CO_Leather_V.Select(l=> new CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = CO_LeatherSizeColor_V.Select(d=>new CuttingOrderDetail {cuttingOrderNo = d.OrderNo}).ToList()
}).ToList();
However, CO_LeatherSizeColor_V does not reference l, so you're going to get everything in that table, every time. You might want something like:
details = l.LeatherSizeColor.Select(d=>new CuttingOrderDetail {cuttingOrderNo = d.OrderNo}).ToList()
for that line instead.

Joining in LINQ to select a sublist within a list

I have two classes as follows:
public class HRM_SERVICE_PERD_BNFT_DTLModel
{
public string SRVC_PERD_BNFT_CODE { get; set; }
public string RTR_BNFT_CODE { get; set; }
public string RTR_BNFT_NAME { get; set; }
public string RTR_BNFT_CALC_MODE { get; set; }
public string SAL_HEAD_CODE { get; set; }
public string SAL_HEAD_NAME { get; set; }
public string RTR_BNFT_IN_PERCENT { get; set; }
public string RTR_BNFT_AMOUNT { get; set; }
public string RTR_BNFT_INACTV_DATE { get; set; }
public short? RTR_BNFT_SLNO { get; set; }
}
public class HRM_RETIREMENT_BENEFITModel : BaseModel
{
public string RTR_BNFT_CODE { get; set; }
public string RTR_BNFT_NAME { get; set; }
public string RTR_BNFT_SRTNM { get; set; }
public string RTR_BNFT_REM { get; set; }
public short? RTR_BNFT_SLNO { get; set; }
}
Now I want to select data from the first model for a specific 'SRVC_PERD_BNFT_CODE', then I need to select the 'RTR_BNFT_NAME' from the second table for all the filtered data along with some other value from the first model. I'm trying kind of joining, but not getting the name. It's showing system.collection.string instead of value.
Here is what I'm trying so far:
public List<HRM_SERVICE_PERD_BNFT_DTLModel> GetBenefitData(string mstcode)
{
var model2 = DataContext.HRM_SERVICE_PERD_BNFT_DTL.AsEnumerable().Where(m => m.SRVC_PERD_BNFT_CODE == mstcode).Select(s=>s).ToList();
var model = DataContext.HRM_SERVICE_PERD_BNFT_DTL.AsEnumerable().Where(m => m.SRVC_PERD_BNFT_CODE == mstcode)
.Select(s => new HRM_SERVICE_PERD_BNFT_DTLModel
{
RTR_BNFT_CODE = s.RTR_BNFT_CODE,
RTR_BNFT_SLNO = s.RTR_BNFT_SLNO,
RTR_BNFT_CALC_MODE = s.RTR_BNFT_CALC_MODE,
RTR_BNFT_AMOUNT = (s.RTR_BNFT_AMOUNT).ToString(),
RTR_BNFT_NAME = (from x in model2
join c in DataContext.HRM_RETIREMENT_BENEFIT on x.RTR_BNFT_CODE equals c.RTR_BNFT_CODE into p
from b in p.AsEnumerable()
select b.RTR_BNFT_NAME).ToList().ToString(),
RTR_BNFT_IN_PERCENT = (s.RTR_BNFT_IN_PERCENT).ToString()
}).ToList();
return model;
}
What I'm doing wrong? Please help.
Following is suspicious.
.ToList().ToString()
Remove the ToString part and replace it with something like FirstorDefault, then it should work.
Reason for getting something like System.Collection.String is that List<T>.ToString() is usually typename until it is overridden in some way.
Following minimal snipped produce System.Collections.Generic.List1[System.String]`
List<String> list = new List<String>();
var str = list.ToString();
Console.WriteLine(str); //System.Collections.Generic.List`1 [ System.String ]

most efficient Entity Framework Code First method of flattening / projecting parent entity with specific child

I have a parent entity Widget with core members and multiple WidgetTranslation children that have language translated members i.e. Description text available in English, French, German etc.
e.g.
public class Widget
{
public int Id { get; set; }
public string Code { get; set; }
public virtual ICollection<WidgetTranslation> WidgetTranslations { get; set; }
}
public class WidgetTranslation
{
public int WidgetId { get; set; }
public virtual Widget Widget { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
}
What is the most efficient method of querying the widget collection, flattening for a given LanguageId & projecting to a TranslatedWidget DTO
public class TranslatedWidget
{
public int Id { get; set; }
public string Code { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
}
Given languageId I've started with
DbSet.Select(w => new TranslatedWidget
{
Id = w.Id,
Code = w.Code,
LanguageId = w.LanguageId,
Name = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Name,
Description = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Description,
Summary = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Summary
});
But I've a feeling this is inefficient and won't scale for more properties on WidgetTranslation.
Thanks
Use SelectMany to flatten structures via a single join:
var widgetQuery = from w in dbSet.Widgets
from wt in w.WidgetTranslations
where wt.Language == languageId
select new TranslatedWidget
{
Id = w.Id,
Code = w.Code,
LanguageId = w.LanguageId,
Name = wt.Name,
Description = wt.Description,
Summary = wt.Summary
});
I'm assuming here that you only have a single translation for each widget in a given language.
I would move Name, Description and Summary into a nested class of your DTO...
public class TranslatedWidgetTranslation
{
public string Name { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
}
public class TranslatedWidget
{
public int Id { get; set; }
public string Code { get; set; }
public int LanguageId { get; set; }
public TranslatedWidgetTranslation Translation { get; set; }
}
Then you can project into that class and need First only once which would result in only one TOP(1) subquery in SQL instead of three:
DbSet.Select(w => new TranslatedWidget
{
Id = w.Id,
Code = w.Code,
LanguageId = languageId,
Translation = w.WidgetTranslations
.Where(wt => wt.LanguageId == languageId)
.Select(wt => new TranslatedWidgetTranslation
{
Name = wt.Name,
Description = wt.Description,
Summary = wt.Summary
})
.FirstOrDefault()
});
You must use FirstOrDefault here, First is not supported in a LINQ-to-Entities projection.
If you don't want that nested type you can project into anonymous types first and then convert into your final class, but the code will be a bit longer:
DbSet.Select(w => new
{
Id = w.Id,
Code = w.Code,
LanguageId = languageId,
Translation = w.WidgetTranslations
.Where(wt => wt.LanguageId == languageId)
.Select(wt => new
{
Name = wt.Name,
Description = wt.Description,
Summary = wt.Summary
})
.FirstOrDefault()
})
.AsEnumerable()
.Select(x => new TranslatedWidget
{
Id = x.Id,
Code = x.Code,
LanguageId = x.LanguageId,
Name = x.Translation != null ? x.Translation.Name : null,
Description = x.Translation != null ? x.Translation.Description : null,
Summary = x.Translation != null ? x.Translation.Summary : null
});

Resources