How to add iOrderedQueryable results to a list? - c#

I'm trying to add my database results to list. Here's my class:
class MyClass
{
public string Tick { get; set; }
public string Exchange { get; set; }
public double Price { get; set; }
public double Volume { get; set; }
}
Here's my routine:
var myList = new List<MyClass>();
foreach (var element in compsList)
{
myList.Add(Price_tbl
.Where(p => p.Ticker.Equals(element.Tick) && p.Tick_datetime <= DateTime.Today)
.GroupBy(p => new { Comp = p.Ticker })
.Select(p => new MyClass {
Tick = p.Key.Comp,
Exchange = element.Exchange,
Price = p.OrderByDescending(c => c.Tick_datetime).Select(c => c.Close_price).FirstOrDefault(),
Volume = (p.Sum(c => c.Volume) / 52),
}));
}
But I'm getting the error:
cannot convert from 'System.Linq.IQueryable<UserQuery.MyClass>' to 'UserQuery.MyClass'
Is there another way to add the results to a list? (I've been racking my brain on this for a few hours now.)

Related

To find the best Projects depending on the Project Likes, Project Connected and Project Rating

I have this table:
PL_ProjectLikes
PC_ProjectConnect
PR_ProjectRating
P_Project
PL_PageLayout
This is my link query:
List<PProject> p = ctx.PProject.Where(x => x.PCountryCode == cC && x.PParentalGuidence == r).ToList();
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
Now PL_PageLayout has a field called PL_P_Id or PlPId, this is a guid.
What i want is to take theses tables figure out a rating or sum or count to pull the best projects to be filtered at the top of the list.
What i have done to extract each of these tables by grouping them with the PIdG which is a guid and is liked to each of the tables from the project and each project is a PL_PageLayout.
Extracted values from the tables:
PL_ProjectLIke:
var plike = ctx.PlProjectLike.Where(x => x.PlValue == "Like").Select(c => c).GroupBy(g => new { g.PlPIdG }, (key, group) => new { sumR = group.Count(), pidG = key.PlPIdG });
List<string> p0p = plike.Select(t => t.pidG).ToList();
PR_ProjectRating:
var prating = ctx.PrProjectRating.Where(x => x.PrIsDeleted == false).Select(k => k).GroupBy(g => new { g.PrPIdG }, (key, group) => new { sumR = group.Sum(k => k.PrValue), pidG = key.PrPIdG });
List<string> p0 = prating.Select(t => t.pidG).ToList();
PC_ProjectConnect:
var pconnect = ctx.PcProjectConnect.Where(x => x.PcStatus == "Connected").Select(c => c).GroupBy(g => new { g.PcPIdG }, (key, group) => new { sumR = group.Count(), pidG = key.PcPIdG });
List<string> p0pp = pconnect.Select(t => t.pidG).ToList();
How do i combine these filters above to find the best projects or pagelayouts using linq?
I tried this:
pppp = pppp.OrderBy(c => p0.Contains(c.PlPId) ? p0.IndexOf(c.PlPId) : int.MaxValue).ToList();
Which works and gets the best projects by the sum of the ratings for each project, but how do i combine the other two querys to find the best project?
Would this be the answer or would this just get the query of the last set:
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
pppp = pppp.OrderBy(c => p0.Contains(c.PlPId) ? p0.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0p.Contains(c.PlPId) ? p0p.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0pp.Contains(c.PlPId) ? p0p.IndexOf(c.PlPId) : int.MaxValue).ToList();
Every time im liking a project as im testing its pushing the project down the list so that bit of code above is not working but making some progress
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
pppp = pppp.OrderBy(c => p0.Contains(c.PlPId) ? p0.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0p.Contains(c.PlPId) ? p0p.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0pp.Contains(c.PlPId) ? **p0pp**.IndexOf(c.PlPId) : int.MaxValue).ToList();
I have put some test code together at RexTester but I am not sure of your question. I think you can just order the result lists as they are created, or am I just misunderstanding the question
public class PlProjectLike
{
public int PlId { get; set; }
public Guid PlPIdG { get; set; }
public int PlUId { get; set; }
public string PlValue { get; set; }
public DateTime PlCreatedDate { get; set; }
}
public class PcProjectConnect
{
public int PcId { get; set; }
public Guid PcPIdG { get; set; }
public int PcUId { get; set; }
public DateTime PcCreatedDate { get; set; }
public string PcStatus{ get; set; }
}
public class PrProjectRating
{
public int PrId { get; set; }
public int PrUId { get; set; }
public string PrText { get; set; }
public int PrValue { get; set; }
public Guid PrPIdG { get; set; }
public DateTime PrCreatedDate { get; set; }
public bool PrIsDeleted{ get; set; }
}
public class PProject
{
public int PId { get; set; }
public Guid PIdG { get; set; }
public string PName { get; set; }
public DateTime PDateCreated { get; set; }
public bool PDeleted { get; set; }
public int PUId { get; set; }
public int PTtId { get; set; }
public string PCountry { get; set; }
public string PCountryCode { get; set; }
public string PParentalGuidence { get; set; }
public string PConnectionType { get; set; }
}
public class PlPageLayout
{
public int PLId { get; set; }
public Guid PlPId { get; set; }
public string PLName { get; set; }
}
public class CTX
{
public List<PProject> PProject { get; set; }
public List<PlPageLayout> PlPageLayout { get; set; }
public List<PlProjectLike> PlProjectLike { get; set; }
public List<PrProjectRating> PrProjectRating { get; set; }
public List<PcProjectConnect> PcProjectConnect { get; set; }
public CTX()
{
PProject = new List<PProject>();
PlPageLayout = new List<PlPageLayout>();
PlProjectLike = new List<PlProjectLike>();
PrProjectRating = new List<PrProjectRating>();
PcProjectConnect = new List<PcProjectConnect>();
}
}
public class LikeGroup
{
public int sumR { get; set; }
public Guid pidG { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
CTX ctx = new CTX();
String r = "R";
string cC = "us";
// Select project for country and rating
List<PProject> p = ctx.PProject.Where(x => x.PCountryCode == cC && x.PParentalGuidence == r).ToList();
// List of PlPageLayouts where the PlPId is in the selected PProject list
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
// List of Count/PlPIdG from PlProjectLike where the PlValue is 'Like' Ordered by the count descending
List<LikeGroup> plike = ctx.PlProjectLike.Where(x => x.PlValue == "Like").Select(c => c).GroupBy(g => new { g.PlPIdG }, (key, group) => new LikeGroup() { sumR = group.Count(), pidG = key.PlPIdG }).OrderByDescending(dat => dat.sumR).ToList();
// List of Sum(PrValue)/PlPIdG from PrProjectRating where PrIsDeleted is false Ordered by the Sum(PrValue) descending
List<LikeGroup> prating = ctx.PrProjectRating.Where(x => x.PrIsDeleted == false).Select(k => k).GroupBy(g => new { g.PrPIdG }, (key, group) => new LikeGroup(){ sumR = group.Sum(k => k.PrValue), pidG = key.PrPIdG }).OrderByDescending(dat => dat.sumR).ToList();
// List of Count/PlPIdG from PcProjectConnect where PcStatus is Connected Ordered by the count descending
List<LikeGroup> pconnect = ctx.PcProjectConnect.Where(x => x.PcStatus == "Connected").Select(c => c).GroupBy(g => new { g.PcPIdG }, (key, group) => new LikeGroup() { sumR = group.Count(), pidG = key.PcPIdG }).OrderByDescending(dat => dat.sumR).ToList();
List<PlProjectLike> OrderedProjectLikeList =
(from pl in ctx.PlProjectLike
join ord in plike on pl.PlPIdG equals ord.pidG
orderby ord.sumR descending
select pl).ToList();
List<PrProjectRating> OrderedPrProjectRatingList =
(from pr in ctx.PrProjectRating
join ord in prating on pr.PrPIdG equals ord.pidG
orderby ord.sumR descending
select pr).ToList();
List<PcProjectConnect> OrderedPcProjectConnectList =
(from pc in ctx.PcProjectConnect
join ord in prating on pc.PcPIdG equals ord.pidG
orderby ord.sumR descending
select pc).ToList();
}
}
From the help of this answer:
https://stackoverflow.com/questions/65014531/summing-a-value-inside-of-a-anonymous-type
I added the following code to get the best projects:
var ratings =
from r1 in ctx.PrProjectRating
where r1.PrIsDeleted == false
group r1.PrValue by r1.PrPIdG into g
select new
{
Id = g.Key,
Sum = g.Sum(),
};
var likes =
from l in ctx.PlProjectLike
where l.PlValue == "Like"
group 1 by l.PlPIdG into g
select new
{
Id = g.Key,
Count = g.Count(),
};
var connects =
from c1 in ctx.PcProjectConnect
where c1.PcStatus == "Connected"
group 1 by c1.PcPIdG into g
select new
{
Id = g.Key,
Count = g.Count(),
};
var ids = ratings.Select(r => r.Id)
.Union(likes.Select(l => l.Id))
.Union(connects.Select(c => c.Id))
.ToHashSet();
var query =
from i in ids
join ra in ratings on i equals ra.Id into rs
from ra in rs.DefaultIfEmpty()
join l in likes on i equals l.Id into ls
from l in ls.DefaultIfEmpty()
join co in connects on i equals co.Id into cs
from co in cs.DefaultIfEmpty()
select new
{
Id = i,
Ratings = ra?.Sum ?? 0,
Likes = l?.Count ?? 0,
Connects = co?.Count ?? 0,
};
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
pppp = query.OrderByDescending(x => x.Ratings + x.Likes + x.Connects).SelectMany(j => pppp.Where(s => s.PlPId == j.Id)).ToList();

C# how to remove duplicate objects from a list

I want to remove duplicate objects from a list. My code works, but I'm still afraid I'll make a mistake. Especially if the amount of data is larger, this solution doesn't make sense to me. I ask for your comments on my code.
// Print the list with duplicates
PrintList(listWithDuplicates);
// This code is not working
noDuplicates = listWithDuplicates.Distinct().ToList();
// This code is working but I am not sure if it is good practice
// especially if I have a large number of data
noDuplicates = listWithDuplicates
.GroupBy(x => x.input1)
.Select(x => x.First())
.GroupBy(x => x.input2)
.Select(x => x.First())
.GroupBy(x => x.output1)
.Select(x => x.First())
.GroupBy(x => x.output2)
.Select(x => x.First())
.ToList();
// Print the list without duplicates
PrintList(noDuplicates);
Console.ReadLine();
}
class Data
{
public string input1 { get; set; }
public string input2 { get; set; }
public string output1 { get; set; }
public string output2 { get; set; }
}
You tried to use .Distinct() without further telling it how to compare instances of your Data-class.
Therefore you could create a Comparer class which you'd then pass to .Distinct() as a parameter:
public class Data
{
public string input1 { get; set; }
public string input2 { get; set; }
public string output1 { get; set; }
public string output2 { get; set; }
}
public class DataComparer : EqualityComparer<Data>
{
public override bool Equals(Data x, Data y)
{
if (x.input1 == y.input1 &&
x.input2 == y.input2 &&
x.output1 == y.output1 &&
x.output2 == y.output2)
{
return true;
}
return false;
}
public override int GetHashCode(Data obj)
{
return $"{obj.input1}{obj.input2}{obj.output1}{obj.output2}".GetHashCode();
}
}
Here is an example:
var dataList = new List<Data>()
{
new Data(){ input1="A", input2="B", output1="B", output2="A"},
new Data(){ input1="A", input2="B", output1="B", output2="A"},
new Data(){ input1="C", input2="D", output1="D", output2="C"},
new Data(){ input1="C", input2="D", output1="D", output2="C"}
};
dataList = dataList.Distinct(new DataComparer()).ToList();
A friend showed me how to do the job without a comparer and without override methods.
noDuplicates = listWithDuplicates.GroupBy(x => new { x.input1, x.input2, x.output1, x.output2 }).Select(y => y.First()).ToList();

Grouping Results in LINQ

I am currently returning a list with Incident Names and Occurrence Dates. I am grouping the returned list by month and year. I need to include one more item in that list which is another list grouped by Incident Names and total per incident. I have the grouping by year and month working, having issues with the second part.
My models:
public class IncidentTrendList
{
public int Year { get; set; }
public int Month { get; set; }
public List<IncidentList> IncidentList { get; set; }
}
public class IncidentList
{
public int IncidentTotal { get; set; }
public string IncidentName { get; set; }
}
public class IncidentRiskMatrix
{
public DateTime Date { get; set; }
public string IncidentName { get; set; }
}
Group by logic:
var groupedList = IncidentRiskMatrix
.GroupBy(u => new
{
Month = u.Date.Month,
Year = u.Date.Year,
})
.Select(grp => new IncidentTrendList
{
Month = grp.Key.Month,
Year = grp.Key.Year,
IncidentList ---> this is a list
}).ToList();
After the group by, in the .Select (IncidentList). How would I group the Incident Names and total per incident and add that item to that list "IncidentList".
If you name your classes more appropriately:
public class IncidentTrend
{
public int Year { get; set; }
public int Month { get; set; }
public List<IncidentsByType> IncidentsByType { get; set; }
}
public class IncidentsByType
{
public int Total { get; set; }
public string Name { get; set; }
}
public class IncidentRiskMatrix
{
public DateTime Date { get; set; }
public string IncidentName { get; set; }
}
The answer becomes more apparent:
var groupedList = incidentsRiskMatrix
.GroupBy(u => new
{
u.Date.Month,
u.Date.Year
})
.Select(grp => new IncidentTrend
{
Month = grp.Key.Month,
Year = grp.Key.Year,
// from each group
IncidentsByType = grp
// group the items by their IncidentName
.GroupBy(x => x.IncidentName)
// and select new IncidentByType
.Select(x => new IncidentsByType
{
// by getting the amount of items in the group
Total = x.Count(),
// and the key of the group
Name = x.Key
})
.ToList()
})
.ToList();
Try:
var groupedList = new List<IncidentRiskMatrix>() //change this to the list of IncidentRiskMatrix variable
.GroupBy(u => new
{
Month = u.Date.Month,
Year = u.Date.Year,
})
.Select(grp => new IncidentTrendList
{
Month = grp.Key.Month,
Year = grp.Key.Year,
IncidentList = grp.GroupBy(x => x.IncidentName).Select(y => new IncidentList()
{
IncidentName = y.Key,
IncidentTotal = y.Count()
}
).ToList()
}).ToList();

Applying a Linq to Entities join on my code

I have code that works, but I worked around a 'Join' in Linq to Entities, because I could not figure it out.
Could you please show me how to succesfully apply it to my code?
My desired result is a dictionary:
Dictionary<string, SelectedCorffData> dataSelectedForDeletion = new Dictionary<string, SelectedCorffData>();
The above mentioned class:
public class SelectedCorffData
{
public long CorffId { get; set; }
public string ReportNumber { get; set; }
public DateTime CorffSubmittedDateTime { get; set; }
}
Please note the 'intersectResult' I am looping through is just a string collection.
Here is my code:
DateTime dateToCompare = DateTime.Now.Date;
Dictionary<string, SelectedCorffData> dataSelectedForDeletion = new Dictionary<string, SelectedCorffData>();
foreach (var mafId in intersectResult)
{
var corffIdsPerMaf = context
.Mafs
.Where(m => m.MafId == mafId)
.Select(m => m.CorffId);
var corffIdForMaf = context
.Corffs
.Where(c => corffIdsPerMaf.Contains(c.Id))
.OrderByDescending(c => c.CorffSubmittedDateTime)
.Select(c => c.Id)
.First();
//Selected close-out forms, whose MAF's may be up for deletion, based on date.
var corffData = context
.Corffs
.Where(c => c.Id == corffIdForMaf && System.Data.Entity.DbFunctions.AddYears(c.CorffSubmittedDateTime, 1).Value > dateToCompare)
.Select(c => new SelectedCorffData () { CorffId = c.Id, ReportNumber = c.ReportNumber, CorffSubmittedDateTime = c.CorffSubmittedDateTime })
.FirstOrDefault();
if(corffData != null)
{
dataSelectedForDeletion.Add(mafId, corffData);
}
}
Please note: this is not just a simple join. If it can't be simplified, please tell me. Also please explain why.
The code below I don't think is exactly right but it is close to what you need. I simulated the database so I could get the syntax correct.
namespace System
{
namespace Data
{
namespace Entity
{
public class DbFunctions
{
public static Data AddYears(DateTime submittedTime, int i)
{
return new Data();
}
public class Data
{
public int Value { get; set; }
}
}
}
}
}
namespace ConsoleApplication23
{
class Program
{
static void Main(string[] args)
{
Context context = new Context();
int dateToCompare = DateTime.Now.Year;
var corffIdsPerMaf = context.Mafs.Select(m => new { id = m.CorffId, mafs = m}).ToList();
var corffIdForMaf = context.Corffs
.Where(c => System.Data.Entity.DbFunctions.AddYears(c.CorffSubmittedDateTime, 1).Value > dateToCompare)
.OrderByDescending(c => c.CorffSubmittedDateTime).Select(c => new { id = c.Id, corff = c}).ToList();
var intersectResult = from p in corffIdsPerMaf
join f in corffIdForMaf on p.id equals f.id
select new SelectedCorffData() { CorffId = p.id, ReportNumber = f.corff.ReportNumber, CorffSubmittedDateTime = f.corff.CorffSubmittedDateTime };
Dictionary<string, SelectedCorffData> dataSelectedForDeletion = intersectResult.GroupBy(x => x.ReportNumber, y => y).ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
public class Context
{
public List<cMafs> Mafs { get; set;}
public List<cCorffs> Corffs { get; set;}
}
public class cMafs
{
public int CorffId { get; set; }
}
public class cCorffs
{
public DateTime CorffSubmittedDateTime { get; set; }
public int Id { get; set; }
public string ReportNumber { get; set; }
}
public class Test
{
}
public class SelectedCorffData
{
public long CorffId { get; set; }
public string ReportNumber { get; set; }
public DateTime CorffSubmittedDateTime { get; set; }
}
}

Object Type conversion while doing Group By

I have a List. I need to find the unique ExistingData records by applying Group By. Following code works.
var distinctItemsWorking = myCostPages
.GroupBy(x => new {
x.CostPageContent.Program,
x.CostPageContent.Group,
x.CostPageContent.Sequence })
.Select(y => y.First());
Now I need to convert the unique list into a List. How can we achieve this conversion when we do Grouping?
C# Method
public List<CostPage> GetCostPages(SearchEntity search, int pageIndex, int pageSize)
{
List<ExistingData> AllData = GetExistingData();
var allMatchingValues = from existingDatas in AllData
where existingDatas.CostPageContent.Program == search.Program
select existingDatas;
var query = allMatchingValues;
List<ExistingData> currentSelectionForExistingData = query
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToList();
//var distinctItems = currentSelectionForExistingData.GroupBy(x => new { x.CostPageContent.Program, x.CostPageContent.Group, x.CostPageContent.Sequence })
// .Select(y => new CostPage()
// {
// CostPageContent = y.CostPageContent
// }
// );
var distinctItemsWorking = currentSelectionForExistingData.GroupBy(x => new { x.CostPageContent.Program, x.CostPageContent.Group, x.CostPageContent.Sequence })
.Select(y => y.First());
List<CostPage> myCostPages = new List<CostPage>();
foreach (ExistingData exist in distinctItemsWorking)
{
CostPage c = new CostPage();
c.CostPageContent = exist.CostPageContent;
myCostPages.Add(c);
}
return myCostPages;
}
Other Classes
public class ExistingData
{
public CostPageNumberContent CostPageContent { get; set; }
public string ItemID { get; set; }
}
public class CostPage
{
public CostPageNumberContent CostPageContent { get; set; }
}
public class CostPageNumberContent
{
public string Program { get; set; }
public string Group { get; set; }
public string Sequence { get; set; }
}
public class SearchEntity
{
public string Program { get; set; }
public string Sequence { get; set; }
public string ItemID { get; set; }
}
If you are trying to replace the foreach, you can do something like this:
var myCostPages = currentSelectionForExistingData
.GroupBy(x => new { x.CostPageContent.Program, x.CostPageContent.Group,
x.CostPageContent.Sequence })
.Select(y => new CostPage { CostPageContent = y.First().CostPageContent })
.ToList();
Putting the creation of the CostPage objects into GroupBy would make no sense. The Select is the correct place to perform this conversion.

Categories