I'm using Linq queries to select from CRM 2013 with my webservice.
My final entity looks like this:
class FOO{
Guid fooId{get;set;}
String fooName{get;set;}
List<Car> fooCars{get;set;}
List<House> fooHouses{get;set;}
}
Where Car looks like this:
class Car{
Guid carId{get;set;
String carName{get;set;}
Guid carFooId{get;set;}
}
And House looks like:
class House{
Guid houseId{get;set;}
String houseName{get;set;}
Guid houseFooId{get;set;}
}
Now, my problem is the following:
I wanna query only once the crm and retrieve a list of FOO with all lists inside it. At the moment I do like this:
List<FOO> foes = crm.fooSet
.Where(x => x.new_isActive != null && x.new_isActive.Value = true)
.Select(x => new FOO(){
fooId = x.Id,
fooName = x.Name,
fooCars = crm.carSet.Where(c => c.fooId == x.Id)
.Select(c => new Car(){
carId = c.Id,
carName = c.Name,
carFooId = c.fooId
}).ToList(),
fooHouses = crm.houseSet.Where(h => h.fooId == x.Id)
.Select(h => new House(){
houseId = h.Id,
houseName = h.Name,
houseFooId = h.fooId
}).ToList()
}).ToList();
My aim is to use LinQ with the non-lambda queries and retrieve all the datas I need with a join and a group-by, but I don't really know how to achieve it, any tip?
Thanks all
I think what you are looking for is a group join:
var query= from f in crm.fooSet
join c in crm.carSet on c.fooId equals f.Id into cars
join h in crm.houseSet on h.fooId equals f.Id into houses
where f.new_isActive != null && f.new_isActive.Value == true
select new FOO{ fooId = f.Id,
fooName = f.Name,
fooCars=cars.Select(c => new Car(){
carId = c.Id,
carName = c.Name,
carFooId = c.fooId
}).ToList(),
fooHouses=houses.Select(h => new House(){
houseId = h.Id,
houseName = h.Name,
houseFooId = h.fooId
}).ToList()
};
Related
I want to convert this SQL query to EF Core code.
I don't want to use LINQ, any possibility?
with cat (id, id_parent, name) as
(
select id, id_parent, name
from categories
where categories.id = 9
union all
select e.id, e.id_parent, e.name
from dbo.categories e
inner join brands b on b.id_parent = e.id
);
select * from cat;
If I get your question correctly this would work for you:
var result = await _dbContext.Categories
.Where(x => x.Id == 9)
.Select(x => new { Id = x.Id, Parent = x.IdParent, Name = x.Name})
.Concat(
_dbContext.Categories.Join(_dbContext.Brands, cat=> cat.Id, brand=> brand.IdParent, (cat,brand)=>cat)
.Select(x => new { Id = x.Id, Parent = x.IdParent, Name = x.Name }))
.ToListAsync();
I have 4 tables (Group, Student, Mark, StudentFile, and want to write my SQL query using LINQ in C#.
Here is my query
SELECT
S.Id,
S.FirstName,
S.LastName,
S.MiddleName,
SUM(M.CountOfPasses) CountOfPasses,
(SELECT SUM(CountOfPassesWithARespectful) FROM StudentFile WHERE StudentId = S.Id) WithARespectful
FROM Student S
LEFT JOIN Mark M ON S.Id = M.StudentId
GROUP BY S.Id, S.FirstName, S.LastName, S.MiddleName
I've already tried something like this:
var students = (from G in context.Group
let v = G.Id
from S in context.Student.Where(x => v == x.GroupId)
from F in context.StudentFile.Where(x => x.StudentId == S.Id).DefaultIfEmpty()
from M in context.Mark.Where(x => x.StudentId == S.Id).DefaultIfEmpty()
group new
{
F.CountOfPassesWithArespectful,
M.CountOfPasses,
S.Id
}
by new
{
S.Id,
S.FirstName,
S.LastName,
S.MiddleName,
S.StartCourse,
G.Name,
S.Alphagroup
} into GSF
select new DTOStudent
{
Id = GSF.Key.Id,
FirstName = GSF.Key.FirstName,
LastName = GSF.Key.LastName,
MiddleName = GSF.Key.MiddleName,
CountOfPasses = (int)GSF.Sum(p=>p.CountOfPasses),
WithRespectful = (int)GSF.Sum(x => x.CountOfPassesWithArespectful),
WithOutRespectful = (int)GSF.Sum(x => x.CountOfPasses) - (int)GSF.Sum(x => x.CountOfPassesWithArespectful),
Course = ClassMethods.GetAgeFromDates((DateTime)GSF.Key.StartCourse).ToString() +
ClassMethods.GetShortGroupName(GSF.Key.Name) + GSF.Key.Alphagroup.ToUpper()
}).Distinct().ToList();
I want to sort the data based on CreatedUtc time. I have tried to use Reverse function, it seems to work out but still looking for some alternate option.
var result = _participantRepo.AsQueryable().Where(x => x.Id == ParticipantId).SelectMany(x =>
x.Relations).ToList().Where(x => x.UserId != AppUserId).Select(r => new RelationVM
{
IsOwner = r.UserId == participant.CreatedByUserId,
FirstName = r.FirstName,
LastName = r.LastName,
Email = r.Email,
UserId = r.UserId,
RelationType = r.RelationType,
Role = r.Role,
IsAccepted = r.IsAccepted,
AvatarUrl = r.AvatarUrl,
CreatedUtc = r.CreatedUtc
}).Reverse().ToList();
There are 2 things you need to concern:
You can sort the elements of a sequence by using OrderBy
You should not .ToList() when you have not done, So you might to read LINQ deferred (or immediate?) execution to have a better understanding.
As a result, your query should look like this
var result = _participantRepo.AsQueryable().Where(x => x.Id == ParticipantId).SelectMany(x =>
x.Relations).Where(x => x.UserId != AppUserId).Select(r => new RelationVM
{
IsOwner = r.UserId == participant.CreatedByUserId,
FirstName = r.FirstName,
LastName = r.LastName,
Email = r.Email,
UserId = r.UserId,
RelationType = r.RelationType,
Role = r.Role,
IsAccepted = r.IsAccepted,
AvatarUrl = r.AvatarUrl,
CreatedUtc = r.CreatedUtc
}).Reverse().OrderBy(g => g.CreatedUtc).ToList();
How about .OrderBy(g => g.CreatedUtc) ?
How to group SubGroup to create list of Continents where each Continent has it own counties and each country has its own cities like this table
Here is the t-sql:
select Continent.ContinentName, Country.CountryName, City.CityName
from Continent
left join Country
on Continent.ContinentId = Country.ContinentId
left join City
on Country.CountryId = City.CountryId
and the result of t-sql:
I tried this but it groups the data in wrong way i need to group exactly like the above table
var Result = MyRepository.GetList<GetAllCountriesAndCities>("EXEC sp_GetAllCountriesAndCities");
List<Continent> List = new List<Continent>();
var GroupedCountries = (from con in Result
group new
{
con.CityName,
}
by new
{
con.ContinentName,
con.CountryName
}
).ToList();
List<Continent> List = GroupedCountries.Select(c => new Continent()
{
ContinentName = c.Key.ContinentName,
Countries = c.Select(w => new Country()
{
CountryName = c.Key.CountryName,
Cities = c.Select(ww => new City()
{
CityName = ww.CityName
}
).ToList()
}).ToList()
}).ToList();
You need to group everything by continent, these by country and the countries by city:
List<Continent> List = MyRepository.GetList<GetAllCountriesAndCities>("EXEC sp_GetAllCountriesAndCities")
.GroupBy(x => x.ContinentName)
.Select(g => new Continent
{
ContinentName = g.Key,
Countries = g.GroupBy(x => x.CountryName)
.Select(cg => new Country
{
CountryName = cg.Key,
Cities = cg.GroupBy(x => x.CityName)
.Select(cityG => new City { CityName = cityG.Key })
.ToList()
})
.ToList()
})
.ToList();
You should apply grouping twice
var grouped = Result
.GroupBy(x => x.CountryName)
.GroupBy(x => x.First().ContinentName);
var final = grouped.Select(g1 => new Continent
{
ContinentName = g1.Key,
Countries = g1.Select(g2 => new Country
{
CountryName = g2.Key,
Cities = g2.Select(x => new City { CityName = x.CityName }).ToList()
}).ToList()
});
I know this is old, but I wanted to mention a much easier way per microsoft that is a bit more readable. This is an example with only 2 levels though but it will most likely work for others who reach this page (like me)
var queryNestedGroups =
from con in continents
group con by con.ContinentName into newGroup1
from newGroup2 in
(from con in newGroup1
group con by con.CountryName)
group newGroup2 by newGroup1.Key;
The documentation for that is at
https://learn.microsoft.com/en-us/dotnet/csharp/linq/create-a-nested-group
and is using a Student object as an example
I do want to mention that the method they use for printing is harder than just creating a quick print function on your continent object
I have two tables User & Employee.
+-------Supervisor----------+
SupervisorId
Password
+---------------------+
+-------Employee----------+
EmployeeId
EmployeeSupervisorId
EmployeeName
+---------------------+
This is what I am doing so far
SupervisorName = db.Employee.Where(m => m.EmployeeSupervisorId == m.SupervisorId).Select(q => q.EmployeeName).ToList()
I am not understanding the concept of how I join my Employee table to itself so that I can get a list of Employee and their corresponding Supervisor Name
You can do the below
SupervisorName = db.Employee
.Join(db.Supervisor,
emp => emp.EmployeeSupervisorId,
sup => sup.SupervisorId,
(emp, sup)=> new {SupervisorName = emp.EmployeeName})
.Select(x=>x)
.ToList();
SupervisorName = db.Employee.
Join(db.Supervisoer, e => e.EmployeeSupervisorId, s => s.SupervisorId, (e, s) => new { Employee = e, Supervisor = s}.
ToList().
Select(e => e.EmployeeName).
ToList();
You can use a simple subquery like this
var result = db.Employee.Select(e => new
{
Employee = e,
SupervisorName = db.Employee
.Where(s => s.EmployeeId == e.EmployeeSupervisorId)
.Select(s => s.EmployeeName).FirstOrDefault()
}).ToList();
Note that if you have EmployeeSupervisorId defined as a foreign-key pointing back to EmployeeId, the Linq2Sql will automatically create a EmployeeSupervisor property (which would be an Employee object)
var list = from e in db.Employee
// where e.......
select new {
Name = e.EmployeeName,
Supervisor = e.EmployeeSupervisor.EmployeeName,
// otherdetails = e......
}
If you haven't defined the foreign key, you have to specify it explicitly in the query:
var list = from e in db.Employee
join s in db.Employee on e.EmployeeSupervisorId equal s.EmployeeId
// where e.......
select new {
Name = e.EmployeeName,
Supervisor = s.EmployeeName,
// otherdetails = e......
}