Entity Framework load data with left join lambda - c#

I want to load from a specific id the list include details with lambda.
I tried it with following code:
// Load User Visitor list
var list = await Context.UserVisitors
.Where(s => s.UserId.Equals(userOwner.Id))
.Select(s => s.UserVisitorId)
.ToListAsync();
foreach (var t in list)
{
UserOwnerVisitors.Add(await Context.User
.Include(u => u.Details)
.Include(u => u.Settings)
.FirstAsync(u => u.Id.Equals(t)));
}
The code works, but it is not efficient. How I can do it in one request with lambda?
Thanks in advance.

I am a little bit blind, as I don't know all your model's relationship, but below you can find what I think is your model, if you edit your question I can perhaps give you an exact answer:
var UserOwnerVisitorsList = from uv in Context.UserVisitors
join u in Context.User
on uv.UserId equals u.Id
join det in Context.Details
on det.UserId equals u.Id
join set in Context.Settings
on set.UserId equals u.UserId
where uv.UserId == userOwner.Id
select u;

Related

How to fill a "ViewModel" for dynamic filter which need to get children of different entities?

I'm using ASP.NET Core MVC 2.*, and using McirosoftEntityFrameworkCore.
I have following tables with relation in parentheses:
Categories(1<==>*)CategoryProduct(*<==>1)Products(1<==>*)AttributeProduct(*<==>1)Attributes(*<==>1)AttributeCategories
I want to create a dynamic filter box in my app which my ViewModel for filter box is as following:
Category(Children==>)AttributeCategories(Children==>)Attributes(Children==>)ProductAttributeValues
I'm using Entity Attribute Value for my "ProductAttribute" table.
The queries which I've tried are as follow:
Using LINQ:
var linqQuery = from c in _context.Categories
join cp in _context.CategroyProducts on c.Id equals cp.CategoryId
join p in _context.Products on cp.ProductId equals p.Id
join pa in _context.ProductAttributes on p.Id equals pa.ProductId
join a in _context.Attributes on pa.AttributeId equals a.Id
join ac in _context.AttributeCategories on a.AttributeCategoryId equals ac.Id
where c.Id == categoryId
This query need to use multiple group by which is challenging for me.
Using Include and foreach:
var includeQuery= _context.Categories
.Include(x => x.CategroyProducts)//step1
.ThenInclude(x => x.Product)//step2
.ThenInclude(x => x.ProductAttributes)//step3
.ThenInclude(x => x.Attribute)//step4
.ThenInclude(x => x.AttributeCategory);//step5
The challenge in this query is to going from step1==>step5==>step4==>step3, which I can't achieve that in foreach.
What is the best way to fill the ViewModel?

translate sql to linq extension method inner join with select group by

Good day,
Thanks for your time.
I want to get the latest messages of a chat table by userId and projectId and this is working fine
select * from chatTable inner join
(select max(SendDate) maxtime,[ProjectId] from [chatTable]
group by [ProjectId])latest
on latest.maxtime=chatTable.SendDate and
latest.[ProjectId]=chatTable.[ProjectId]
order by SendDate
As you can see, I am getting the latest messages from the chatTable , with a join that brings the latest project id and the latest message.
How can I have a linq with extension methods?
var messages= await _dbContext.chatTable.....
Thanks
You can first query the inner part like below:
var latest= _dbContext.chatTable.GroupBy(x=>x.ProjectId).Select(x=>new {maxTime=x.Max(y=>y.SendDate), ProjectId=x.Key });
var res=(from ct in _dbContext.ChatTable
join la in latest on la.maxTime equals ct.SendDate and la.ProjectId equals ct.ProjectId).ToList().OrderBy(x=>x.SendDate);
This query should do what you want
_dbContext.ChatTable
.GroupBy(c => c.ProjectId)
.Select(g => g
.OrderByDescending(c => c.SendDate)
.First())
.OrderBy(c => c.SendDate);
This should give what you need:
_dbContext.chatTable
.GroupBy(c => c.ProjectId)
.Select(g => g.OrderBy(c => c.SendDate).LastOrDefault())
Well guys, it seems that linq entity framework has its advantages
this query is better and gets the latest message sent to the latest project
var ultimos = await _dbContext.chatTable .GroupBy(item => item.ProjectId)
.Select(group => new { pId= group.Key, latestMessage= group.OrderByDescending(r=>r.SendDate)
.FirstOrDefault() })
.ToListAsync();
and all the messages are inside the entity

C# : How to get anonymous type from LINQ result

I need to get NewsImage field and list of categories Ids that associated with the news in Many to Many relationship ... but it gives me error:
The type of one of the expressions in the join clause is incorrect.Type inference failed in the call to 'Join'.
My code looks like this
var Result1 = (from c in db.News
join d in db.Categories
on c.NewsId equals d.News.Select(l => l.NewsId)
where c.NewsId == 1
select new { c.NewsImagePath, d.CategoryId }).ToList();
Assuming you have a navigation property defining the n-n relation I would write:
var result = db.News
.Where(x => x.NewsId == 1)
.SelectMany(x => x.Categories,
(news, category) => new { news.NewsImagePath, category.CategoryId })
.ToList();
The problem is inside the on statement.
on c.NewsId equals d.News.Select( l => l.NewsId )
The Select on the right-hand side will return a IEnumerable of news, which is not what you want.
Something like this would technically work:
on c.NewsId equals d.News.Select( l => l.NewsId ).FirstOrDefault()
But it does not make sense logically.
I suspect the whole query should be built differently. I think you want to join when the category list of news contains the news item. In that case, you can't use the join statement, it would look somewhat like this:
from n in db.News
from c in db.Categories
where c.News.Select( ne => ne.NewsId ).Contains( n.NewsId )
select new { n.NewsImagePath, c.CategoryId }

How to use the 'NOT IN' function in LINQ?

var query2 = (from tc in Entities.TutorCourses
join c
in Entities.Course
on tc.CourseId equals c.Id
where tc.CourseId == id
select tc.Username).ToList();
var query1 = Entities.User
.Select(u => u.Role
.Select(p => p.Name)
.Contains("Tutor"));
I am trying to return all the Users from a database that are in query1 except all those Users that are in query2 as above.
How can I achieve this? I tried using returning query1 by adding .Except(query2); in the end but I am not sure which is the best method to implement a 'NOT IN' function in LINQ
That 2nd query just looks wrong. Try this:
var query2 = (from tc in Entities.TutorCourses
join c
in Entities.Course
on tc.CourseId equals c.Id
where tc.CourseId == id
select tc.Username).ToList();
var query1 = Entities.User
.Where(u =>
query1.Any(un => un != u.Username) &&
u.Role.Name.Contains("Tutor"))
.Select(u => u.Role);
If this all query are the same type try to you this method
Intersect
You can use the Any to find matches between two lists, then add a ! to specify that you want the ones that don't match. Here's an example that should work for you:
var excludedList = query1.Where(x => !query2.Any(y => y.Id == x.Id));
How about query1.Where(c=> !query2.Contains(c));

Convert this LINQ to Lambda Expression?

I have a LINQ, it works fine. My question is: how to convert it to Lambda Expression?
var searchResults = from study in dataContext.Studies
join location in dataContext.Locations
on study.LocationID equals location.LocationID
join doctorLocation in dataContext.DoctorLocations
on location.LocationID equals doctorLocation.LocationID
join doctor in dataContext.Doctors
on doctorLocation.DoctorID equals doctor.DoctorID
where doctor.DoctorID == doctorId
select study;
I think LINQ is more natural to me (similar to SQL script). However, in this case, I just want to convert it to Lambda Expression, but I could not make it work.
I got stuck at:
var searchResults = dataContext.Studies.Where(x =>
x.Location.DoctorLocations.FirstOrDefault() != null &&
x.Location.DoctorLocations.FirstOrDefault().DoctorID == doctorId);
This only works for FirstOrDefault. Since there are multiple DoctorLocations, I do not how to write this one.
Try this:
var searchResults = dataContext.Studies.Where(x =>
x.Location != null
&& x.Location.DoctorLocations.Any(dl => dl.DoctorID == doctorId));
you will get all Studies related to at least one DoctorLocation with DoctorID equals doctorId
var searchResults = dataContext.Studies
.Include(x => x.Locations)
.Include(x => x.DoctorLocations)
.Include(x => x.Doctors)
.Where(x => x.[InheritedPathToDoctor].DoctorId == id)
.Select(x => x.[InheritedPathToStudy].Study)
.FirstOrDefault() OR .ToList()
I have made a lot of assumptions here as to how you have set up your context. I've assumed it's a relational database and therefore the includes simply means it returns all data. I haven't tested it though so there are probably a few errors.
You require an include for every class and the where is pretty self explanatory.

Categories