How to perform following query in LINQ? - sql

I have a SQL query need to do in LINQ. Can anyone helps in converting?
SELECT *
FROM profile
WHERE ProfileId <> 1221 AND IsActive = 1 AND
ProfileId NOT IN (SELECT ReportingPerson
FROM ReportingPersons
WHERE Employee = 1221)

var reportingPerson = context.ReportingPersons.Where(x =>
x.Employee == 1221)
.Select(c => c.ReportingPerson
).ToList();
var result = context.Profiles
.Where(x =>
x.ProfileId != 1221 &&
x.IsActive &&
!reportingPerson.Contains(x.ProfileId)
.ToList();

Related

Getting error 'Unable to translate a collection subquery in a projection' when using union and select together in EF Core 7

I wrote a code that EF Core creates an expression for that looks like this:
DbSet<Reception>()
.Include(x => x.Employee)
.Include(x => x.ReceptionSignatures)
.Where(x => x.Employee.FirstName.Contains("mo"))
.Union(DbSet<Reception>()
.Include(x => x.Employee)
.Include(x => x.ReceptionSignatures)
.Where(x => x.Employee.PersonelId.Contains("mo")))
.Union(DbSet<Reception>()
.Include(x => x.Employee)
.Include(x => x.ReceptionSignatures)
.Where(x => x.Employee.LastName.Contains("mo")))
.Union(DbSet<Reception>()
.Include(x => x.Employee)
.Include(x => x.ReceptionSignatures)
.Where(x => x.Employee.NationId.Contains("mo")))
.OrderBy(x => x.Employee.FirstName.CompareTo("mo") == 0 ? 0 : 1)
.Select(r => new ReceptionAllDTO{
ReceptionId = r.Id,
NationId = r.Employee.NationId,
PersonelId = r.Employee.PersonelId,
FirstName = r.Employee.FirstName,
LastName = r.Employee.LastName,
Birthday = r.Employee.Birthday,
RecepDate = r.RecepDate,
Height = r.Height,
Weight = r.Weight,
ReceptionSignatures = r.ReceptionSignatures,
}
)
In Reception entity, I have a relation to Signature like this:
public virtual ICollection<Signature> ReceptionSignatures { get; set; }
but when EF Core wants to create a query for SQL, it throws this exception:
Unable to translate a collection subquery in a projection since either parent or the subquery doesn't project necessary information required to uniquely identify it and correctly generate results on the client side. This can happen when trying to correlate on keyless entity type. This can also happen for some cases of projection before 'Distinct' or some shapes of grouping key in case of 'GroupBy'. These should either contain all key properties of the entity that the operation is applied on, or only contain simple property access expressions.
It seems like you are querying for more data which is really not efficient. Its better to project your required columns using the Select() and then write a Union.
When writing the Union the number of columns Selected must be same as shown below from a code base i wrote 2 weeks ago and which works.
var billPaymentVoucherQuery = _context.Set<BillPaymentVoucher>().AsQueryable();
var billsQuery = _context.Set<Bill>().AsQueryable();
var anon_billsQuery = billsQuery.Where(w => w.InvoiceDate.Date <= filter.AsAtDate.Date)
.Where(w => w.OperationalStatus == OperationalBillStatus.Approved &&
(
w.FinancialStatus == FinancialBillStatus.Pending ||
w.FinancialStatus == FinancialBillStatus.OnHold ||
w.FinancialStatus == FinancialBillStatus.PartiallyApproved ||
w.FinancialStatus == FinancialBillStatus.Approved
))
.Select(s => new
{
VendorName = s.VendorInvoice.Vendor!.Name,
Type = "Bill",
Date = s.InvoiceDate,
Number = Convert.ToString(s.InvoiceNumber),
Amount = s.LineItemTotal + s.VATAmount
}).AsQueryable();
var anon_billPaymentVoucherQuery = billPaymentVoucherQuery
.Where(w => (
w.UpdatedOn.HasValue &&
w.UpdatedOn.Value.Date <= filter.AsAtDate.Date
)
||
(
w.UpdatedOn.HasValue == false &&
w.CreatedOn.Date <= filter.AsAtDate.Date
))
.Where(w => w.BillPaymentVoucherStatus == BillPaymentVoucherStatus.Paid)
.Select(s => new
{
VendorName = s.PaymentApprovedBill.Bill.VendorInvoice.Vendor!.Name,
Type = "Payment",
Date = s.UpdatedOn ?? s.CreatedOn,
Number = Convert.ToString(s.PaymentApprovedBill.Bill.InvoiceNumber + " | " +
s.PaymentVoucherNumber),
Amount = -s.PayAmount
}).AsQueryable();
var unionedQuery = anon_billsQuery.Union(anon_billPaymentVoucherQuery)
.Where(w => string.IsNullOrWhiteSpace(filter.Type) || w.Type == filter.Type);
int pageSize = 2;
bool hasMoreRecords = true;
var transactionData = await unionedQuery.OrderBy(w => w.VendorName)
.ThenBy(w => w.Date)
.Skip((paginator.PageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync(token);

How to Convert Sql to Linq with Distinct(id)

select count(distinct LicencePlate) from MT_Vehicle where IsDeleted=0 and CreatedBy = 1
var count = MT_Vehicle.Where(x => x.IsDeleted==0 && x.CreatedBy == 1)
.Select(x => x.LicencePlate)
.Distinct()
.Count();
You can write that as:
var count = db.MT_Vehicle
.Where( v => v.IsDeleted == 0 && v.CreatedBy == 1 )
.Select(v => v.LicencePlate)
.Distinct()
.Count();

SQL with max(date) to LINQ

I have tried to make the following sql in linq with no luck can some help mw with this?
select * from customer c
where companynumber = 1
and status <> 0
and lastdate = (select max(lastdate) from customer where customernumber = c.customernumber)
Gives 22 records
My best try was this:
_ctx.Customers
.Where(r => r.CompanyNumber == companyNumber && r.CustomerNumber != null && r.Status != 0)
.GroupBy(c => c.CustomerNumber)
.Select(g => new
{
name = g.Key,
count = g.Count(),
date = g.Max(x => x.LastEdited)
})
.OrderBy(c => c.name);
Gives 22.000+ records
But not the result as the above SQL
UPDATE:
The following LINQ does the trick ;o)
from a in _ctx.Customers
where a.CustomerNumber != null && a.CompanyNumber == companyNumber
group a by new { a.CustomerNumber } into g
select g.OrderByDescending(a => a.LastEdited).FirstOrDefault() into c
where c.Status == 1
select c
I had to move the where c.Status == 1 into my first select statment

Entity Framework - Selecting specific columns

I have a successful query that links two tables with a where and orderby clause, but I wanted to add to just select specific columns instead of getting everything back.
PART 1
When I attempt this I get syntax errors on the orderby line, if I remove the orderby line the syntax errors move to the where line.
Error 3 Cannot implicitly convert type 'System.Linq.IOrderedQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?)
IQueryable<VendorProfile> query = _db.VendorProfiles
.Include("VendorCategories")
.Include("VendorsSelected")
.Select(s => new { s.ProfileID, s.Name, s.CompanyName, s.City, s.State, s.DateCreated, s.VendorsSelected, s.VendorCategories })
.Where(x => x.VendorsSelected.Select(s => s.UserName).Contains(HttpContext.Current.User.Identity.Name))
.OrderBy(x => x.DateCreated);
if (criteria.name != string.Empty)
query = query.Where(v => v.Name.Contains(criteria.name));
if (criteria.company != string.Empty)
query = query.Where(v => v.CompanyName.Contains(criteria.company));
if (criteria.startDate != null && criteria.endDate != null)
query = query.Where(v => v.DateCreated > criteria.startDate && v.DateCreated < criteria.endDate);
if (criteria.categories != null && !criteria.categoryMatchAll)
query = query.Where(v => criteria.categories.AsQueryable().Any(cat => v.VendorCategories.Select(vendCat => vendCat.CategoryID).Contains(cat)));
if (criteria.categories != null && criteria.categoryMatchAll)
query = query.Where(v => criteria.categories.AsQueryable().All(cat => v.VendorCategories.Select(vendCat => vendCat.CategoryID).Contains(cat)));
if (criteria.minorityType != null)
query = query.Where(v => v.MinotiryOwned == criteria.minorityType);
if (criteria.diversityClass != null)
query = query.Where(v => v.DiversityClassification == criteria.diversityClass);
return query.ToList();
PART 2
I also wanted to know if I could extract the selected columns into a view model class, so I tired this and I get same results as above on the orderby line
Error 4 Cannot implicitly convert type 'System.Linq.IOrderedQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?)
ANSWER
I think you helped me stumble upon the fact that the types don't match. Making the IQueryable type and the select new type and the return type the SAME makes the syntax happy. Using var does not like.
public IEnumerable<BrowseVendorModel> SearchVendors(CustomSearchModel criteria)
{
IQueryable<BrowseVendorModel> query = _db.VendorProfiles
.Include("VendorCategories")
.Include("VendorsSelected")
.Select(s => new BrowseVendorModel
{
ProfileID = s.ProfileID,
Name = s.Name,
CompanyName = s.CompanyName,
City = s.City,
State = s.State,
DateCreated = s.DateCreated,
VendorsSelected = s.VendorsSelected,
VendorCategories = s.VendorCategories
})
.Where(x => x.VendorsSelected.Select(s => s.UserName).Contains(HttpContext.Current.User.Identity.Name))
.OrderBy(x => x.DateCreated);
if (criteria.name != string.Empty)
query = query.Where(v => v.Name.Contains(criteria.name));
if (criteria.company != string.Empty)
query = query.Where(v => v.CompanyName.Contains(criteria.company));
if (criteria.startDate != null && criteria.endDate != null)
query = query.Where(v => v.DateCreated > criteria.startDate && v.DateCreated < criteria.endDate);
if (criteria.categories != null && !criteria.categoryMatchAll)
query = query.Where(v => criteria.categories.AsQueryable().Any(cat => v.VendorCategories.Select(vendCat => vendCat.CategoryID).Contains(cat)));
if (criteria.categories != null && criteria.categoryMatchAll)
query = query.Where(v => criteria.categories.AsQueryable().All(cat => v.VendorCategories.Select(vendCat => vendCat.CategoryID).Contains(cat)));
if (criteria.minorityType != null)
query = query.Where(v => v.MinotiryOwned == criteria.minorityType);
if (criteria.diversityClass != null)
query = query.Where(v => v.DiversityClassification == criteria.diversityClass);
return query;
}
The first example requires var because you are changing the shape of the query by projecting into anonymous type. The second example can either use var or IQueryable<VendorProfileViewModel> because you are changing the shape of the query by projecting into VendorProfileViewModel.

nHibernate, OR clause with .withSubquery

How can we force nHibernate to generate “OR” clause instead of “AND” clause when using “.withSubquery”
var includeSharedTemplateCategories= EntityFinder.Of<TemplateMappers.FolderEntity>() .Where(e => e.MID == effectiveMemberID) .Where(e => e.CategoryType == "shared_template") .SelectList(e => e.Select(c => c.Id));
var includeNormalCategories = EntityFinder.Of<TemplateMappers.FolderEntity>()
.Where(e => e.MID == MemberID)
.Where(e => e.CategoryType == "template")
.SelectList(e => e.Select(c => c.Id));
var query = EntityFinder.Of<TemplateMappers.TemplateEntity>()
.Where(f => f.TemplateIsActive == 1)
.RestrictionByQuery<TemplateMappers.TemplateEntity, TemplateObject>(options)
.WithSubquery.WhereProperty(e => e.CategoryId).In(includeSharedTemplateCategories)
.WithSubquery.WhereProperty(e => e.CategoryId).In(includeNormalCategories)
.SelectByQuery<TemplateMappers.TemplateEntity, TemplateObject>(options)
.OrderByQuery<TemplateMappers.TemplateEntity, TemplateObject>(options);
“And” is used in condition
this_.fkcategoryid IN (SELECT this_0_.pkcategoryid AS y0_
FROM categories this_0_
WHERE this_0_.mid = xyz AND this_0_.categorytype = 's_template')
And this_.fkcategoryid IN (SELECT this_0_.pkcategoryid AS y0_ FROM categories this_0_
WHERE this_0_.mid = abc AND this_0_.categorytype = 'template');
I’m looking for “OR“ clause between sub-queries.
this_.fkcategoryid IN (SELECT this_0_.pkcategoryid AS y0_ FROM categories this_0_ WHERE this_0_.mid = xyz AND this_0_.categorytype = 's_template')
**OR** this_.fkcategoryid IN (SELECT this_0_.pkcategoryid AS y0_ FROM dbo.tblcategories this_0_ WHERE this_0_.mid = abc AND this_0_.categorytype = 'template');
kris.
var includeSharedAndNormalTemplateCategories = EntityFinder.Of<FolderEntity>()
.Where(e => (e.MID == effectiveMemberID && e.CategoryType == "shared_template") ||
(e.MID == MemberID && e.CategoryType == "template"))
.Select(e => e.Id);
var query = EntityFinder.Of<TemplateEntity>()
.Where(f => f.TemplateIsActive)
.RestrictionByQuery<TemplateEntity, TemplateObject>(options)
.WithSubquery.WhereProperty(e => e.CategoryId).In(includeSharedAndNormalTemplateCategories)
.SelectByQuery<TemplateEntity, TemplateObject>(options)
.OrderByQuery<TemplateEntity, TemplateObject>(options);
SideNote: TemplateIsActive should be/is bool no?