Linq Left Join with Lambda Count - linq

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();

Related

How to group by on first table row many to many relation with left join in LINQ

How can I group by complaint in this scenario?
I get all Data with left join with bellow query
now I want all the application users grouped for every related complaint row
my mean one complaint should have many users that is assigned to how should I group users by
complaint and how to loop through it in order to assign the grouped users to any ViewModel
property
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; }
}
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();
Now I want to have list of all user assigned to each complaint, so how can I do that please?

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?

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/

How to Get Joined Table Data Entity Framework

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();
}

Resources