How to Get Joined Table Data Entity Framework - linq

I have a two models which are
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ShortDescription { get; set; }
public string PostImage { get; set; }
public string Thumbnail { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? PublishedDate { get; set; }
public string CreatedBy { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
And that generates the CategoryPosts table.
Here is my question: I want to get data from the CategoryPosts table to calculate popular categories. How can I reach that data? And what is the best way to do that?

If you want the popular categories you don't need to map the juction table, you can order the Categories by the count of post:
var query=yourContext.Categories.OrderBy(c=>c.Posts.Count);
If you have disabled lazy loading then you should call the Include method before:
var query=yourContext.Categories.Include(c=>c.Posts).OrderBy(c=>c.Posts.Count);
As you can see below, the SQL code generated is using the junction table to check the count of Post that have each Category and order by that criteria:
SELECT
[Project1].[Id] AS [Id],
[Project1].[Name] AS [Name]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[PostCategories] AS [Extent2]
WHERE [Extent1].[Id] = [Extent2].[Category_Id]) AS [C1]
FROM [dbo].[Categories] AS [Extent1]
) AS [Project1]
ORDER BY [Project1].[C1] ASC
The junction table generally is mapped when you need to add an additional column (that excludes both keys of the tables you are joining). In that case you need to create two one-to-many relationships between the juction table and Post and Caterogy respectively.

Thanks octavio ,
I got the idea right now i can easily get like that.
public List<Category> GetPopularCategories()
{
return _categoryRepository.GetAll().OrderBy(c => c.Posts.Count).ToList();
}

Related

LINQ query many to many relation with additional field in join table

I want to get all the records from Complaints either are assigned to users or not and list of all users that the complaint is assigned to grouped by each complaint with LINQ query Left join. these tables have many to many relation table with additional fields like Date etc. I tried a lot pleas if some one help me for this query.
thanks in advance
public class Complaint
{
[Key]
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? Email { get; set; }
[Required]
public string? Complaint{ get; set; }
public ICollection<AsignComplaintToUsers> asignComplaintToUsers { get; set; }
}
public class ApplicationUser : IdentityUser
{
[Column(TypeName = "nvarchar(100)")]
public string? FirstName { get; set; }
[PersonalData]
[Column(TypeName = "nvarchar(100)")]
public string? LastName { get; set; }
public ICollection<AsignComplaintToUsers> asignComplaintToUsers { get; set; }
}
public class AsignComplaintToUsers
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int ComplaintId { get; set; }
[ForeignKey("ComplaintId")]
public Complaint complaint { get; set; }
public string? AsignToId { get; set; }
[ForeignKey("AsignTo")]
public ApplicationUser applicationUser { get; set; }
public string? AsignById { get; set; }
}
with this query I solved the problem
var xyz = (from c in _context.complaints
join AC in _context.asignComplaintToUsers
on c.Id equals AC.ComplaintId into temp
from t in temp.DefaultIfEmpty()
join AppUser in _context.applicationUsers
on t.AsignTo equals AppUser.Id into temp2
from t2 in temp2.DefaultIfEmpty()
select new
{
complaint = c,
asugnSugessionTousers = t,
usersWhoAsignedComplaints = t2
}).ToList();

Linq SQL EF Core subselect always requests ALL columns for tables in subquery from database

I have an ASP.NET Core 3.1 with EF Core Web API running in front of a SQL Server. Front end is Angular.
There is a function where someone is able to select the campaigns that are running for multiple selected clients.
The models involved are:
public partial class Campaign
{
public int CampaignId { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int AdvertiserId { get; set; }
public int SalesHouseId { get; set; }
}
public partial class Customer
{
public int CustomerId { get; set; }
public string CompanyName { get; set; }
public string SearchCode { get; set; }
public string PhoneNumber1 { get; set; }
public string PhoneNumber2 { get; set; }
public string FaxNumber { get; set; }
public string Email { get; set; }
public string CompanyURL { get; set; }
public bool IsOnHold { get; set; }
public DateTime? OnHoldSince { get; set; }
public string OnHoldBy { get; set; }
public .... more fields { get; set; }
}
I use the following LinqSql to pull the campaigns for the selected clients (example):
List<int> selectedClients = new List<int>() { 10414, 19529, 14025 };
var cams = (from cam in _dbContext.Campaigns
join cl in (from cus in _dbContext.Customers.Where(cus =>
selectedClients.Contains(cus.CustomerId))
select new { cus.CustomerId, cus.CompanyName })
on cam.AdvertiserId equals cl.CustomerId
select new { cam.CampaignId, cam.Description, cam.StartDate, cl.CompanyName})
.AsNoTracking()
.ToList();
The result returned is good and all works fine.
BUT I checked the SQL that is send down to the server and noticed that for the sub query ALL columns are requested:
SELECT [c].[CampaignId], [c].[Description], [c].[StartDate], [t].[CompanyName]
FROM [Campaigns] AS [c]
INNER JOIN (
SELECT [c0].[CustomerId], [c0].[ACEndDate], [c0].[ACStartDate], [c0].[ActiveSince], [c0].[AgencyCommission], [c0].[Balance], [c0].[BalanceDate], [c0].[BankAccount], [c0].[CompanyName], [c0].[CompanyURL], [c0].[CreditLimit], [c0].[DebtorNumber], [c0].[Email], [c0].[EmailInvoice], [c0].[EmailOrderConfirmation], [c0].[FaxNumber], [c0].[FinanciallyResponsibleCustId], [c0].[InactiveSince], [c0].[InvDueDays], [c0].[InvFreqMargin], [c0].[InvoiceFrequency], [c0].[InvoiceInfo], [c0].[IsActive], [c0].[IsAdvertiser], [c0].[IsAdvertisingAgency], [c0].[IsAgency], [c0].[IsApprovedAgency], [c0].[IsDirectAdvertiser], [c0].[IsFinanciallyResponsible], [c0].[IsHolding], [c0].[IsOnHold], [c0].[IsOther], [c0].[IsProductionCompany], [c0].[IsTaxable], [c0].[OnHoldBy], [c0].[OnHoldReason], [c0].[OnHoldSince], [c0].[PaymentMethod], [c0].[PhoneNumber1], [c0].[PhoneNumber2], [c0].[PrintOrderConfirmation], [c0].[PrintZeroInvoices], [c0].[SearchCode], [c0].[SetInactiveBy], [c0].[VATId], [c0].[VATNumber]
FROM [Customers] AS [c0]
WHERE [c0].[CustomerId] IN (10414, 19529, 14025)
) AS [t] ON [c].[AdvertiserId] = [t].[CustomerId]
ALL columns from the table in the subquery are send back to the API. I only need the [customerId] and [companyName] fields.
I tried to use a DTO instead of the anonymous select in the subquery but that does not help either.
If the subselect consists of more tables, all columns of all tables in that sub select will be requested from the database.
Does anyone have an idea how to limit the columns from the sub-select here?

Linq Left Join with Lambda Count

I have a Users and a Shipments table. The Shipments table has a property Received. I want to write code to get all Users where all their shipments have been received (received == true) with linq.
Users table
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool NeedsFilament { get; set; }
public ICollection<Shipment> Shipments { get; set; }
Shipments table
public Guid Id { get; set; }
public int Quantity { get; set; }
public DateTime DateShipped { get; set; }
public bool Recieved { get; set; }
public Guid UserId { get; set; }
public User User { get; set; }
What I've done so far in a SQL query that doesn't count the Received props in Shipments but just gets the distinct (it's wrong)
SELECT DISTINCT
[FirstName]
,[LastName]
,[Username]
,[Address]
,[LatestShippedDate]
,[PrinterActive]
,[ProductionDate]
,[ShippedQuantity]
,[Email]
,[PhoneNumber]
,[NeedsFilament]
,[FilamentTrackingNumber]
,[SentFilamentDate]
,[LatestShippedQuantity]
FROM
[dbo].[Users]
LEFT JOIN
Shipments ON Shipments.UserId = Users.Id
WHERE
Shipments.Recieved = 1
AND Users.NeedsFilament = 1
Hello #Pt4r the below Linq statement will do that you want, the below line parse the users_table and compare each element of two tables and keep those elements which statement return true
var newUserTbl = users_table.Where(user=>Shipments.UserId==user.id && Shipments.Recieved).ToList();

How to join 3 tables in linq and get some not included fields in query

I'm implementing asp.net core project. I have 3 tables Apiapp, ApiAppHistory and EntityType. There are three fields with the names SentType, Status and Reason in ApiAppHistory and those fields are of kind Id (int type) in APIApphistory. I joined ApiApp and ApiAppHistory tables in order to get those three fields from ApiAppHistory but because they are of kind int and are unclear when showing the result to the user, I join them with EntityType table which has their related name. In the select part of my query, in addition to ApiApp fields I also need to have SentType, Status and Reason value fields.
Here below is my incomplete query:
var qq = _context.Apiapp
.Include(a => a.Api)
.Include(a => a.Application)
.Include(a => a.Data);
var t12 = (from r in qq
from b in _context.ApiAppHistory
from s in _context.EntityType
where r.LastRequest== b.Id && b.SentType == s.Id
&& b.Reason == s.Id
&& b.Status == s.Id
select new { r, s.name for Reason, s.name for
SentType ,s.name for Status});
I want in select part of my query, obtain name of the fields that I specified from the EntityType table. However, I don't know how to do it. I appreciate if someone helps me.
Here is my EntityType table:
Here are my APIAppHistory and EntityType class model:
public partial class ApiAppHistory
{
public int Id { get; set; }
public int? SentType { get; set; }
public int? Reason { get; set; }
public int? Status { get; set; }
public virtual Apiapp ApiApp { get; set; }
public virtual EntityType StatusNavigation { get; set; }
public virtual EntityType SentTypeNavigation { get; set; }
public virtual EntityType ReasonNavigation { get; set; }
}
public partial class EntityType
{
public EntityType()
{
ApiAppHistoryStatusNavigation = new HashSet<ApiAppHistory>();
ApiAppHistorySentTypeNavigation = new HashSet<ApiAppHistory>();
ApiAppHistoryReasonNavigation = new HashSet<ApiAppHistory>();
}
public int Id { get; set; }
public string Name { get; set; }
public string EntityKey { get; set; }
public virtual ICollection<ApiAppHistory> ApiAppHistoryStatusNavigation { get; set; }
public virtual ICollection<ApiAppHistory> ApiAppHistorySentTypeNavigation { get; set; }
public virtual ICollection<ApiAppHistory> ApiAppHistoryReasonNavigation { get; set; }
}
}

RavenDB using filter with group by

I have a Transaction entity.
I can make group by by (CustomerCode, CustomerName) then select CustomerCode and Total(Amount).
It is easy. But When I Want to filter AtCreated. I have An Error.
Unhandled exception. Raven.Client.Exceptions.InvalidQueryException: Raven.Client.Exceptions.InvalidQueryException: Field 'AtCreated' isn't neither an aggregation operation nor part of the group by key
Query: from Transactions group by CustomerCode, CustomerName where AtCreated >= $p0 select CustomerCode, count() as Total
Parameters: {"p0":"2019-01-01T00:00:00.0000000"}
public class Transactions
{
public string Id { get; set; }
public long TransId { get; set; }
public DateTime AtCreated { get; set; }
public string CustomerCode { get; set; }
public string CustomerName { get; set; }
public string City { get; set; }
public double Amount { get; set; }
public string GXF { get; set; }
}
var transactList = session.Query<Transactions>()
.Where(a=>a.AtCreated >= new DateTime(2019,01,01))
.GroupBy(a => new {a.CustomerCode, a.CustomerName})
.Select(a => new {a.Key.CustomerCode, Total = a.Count()})
.ToList();
How can I Grouping filtered data?
Thank You.
Create a Map-Reduce Index and then query on it.
https://ravendb.net/docs/article-page/4.2/csharp/indexes/map-reduce-indexes
For example, in this example, you can query on 'Category' field because it was indexed (meaning it was part of the Map-Reduce index definition)
See short demo examples in:
https://demo.ravendb.net/

Resources