Linq to objects giving strange error - runtime-error

I have the following code:
List<JobPortalInfo> jobPortalInfos = uow.JobPortalInfoRepository.GetQuery()
.Where(x => x.Job.Id == emailHash.JobId)
.ToList();
var temp = uow.EmailRepository.GetQuery()
.Where(x => jobPortalInfos.Any(y => (y.Contact != null && y.Contact.Id == x.ContactId)))
.ToList();
When I run the 2nd statement, I'm getting the error:
Unable to create a constant value of type 'CR.Data.JobPortalInfo'.
Only primitive types or enumeration types are supported in this context.
JobPortalInfo has a 1-[0 or 1] with Customer and Customer has a 1-* with Email.
Any ideas what I'm doing wrong here?

I figured it out.
jobPortalInfos is Linq to Objects, but EmailRepository is still an IQueryable/Linq To Entites. It doesn't know how to convert the LinqToObject jobPortalInfos to a Sql Server object.
I ended up doing this:
List<JobPortalInfo> jobPortalInfos = uow.JobPortalInfoRepository.GetQuery()
.Where(x => x.Job.Id == emailHash.JobId)
.ToList();
List<long> contactIds = jobPortalInfos
.Where(x => x.Contact != null)
.Select(y => y.Contact.Id)
.ToList();
var temp = uow.EmailRepository.GetQuery()
.Where(x => contactIds.Contains(x.ContactId))
.ToList();
Not sure if there is a more concise way to do this or not, but it seems to work.

Related

Flutter Firestore Query Field in Object

I'm writing a Flutter app and am trying to add documents to a list, where the contractorUserId value field (under jobBids) in Firestore is equal to the logged-in user. The image below shows the structure of my Firestore structure (contractorUserId in jobBids)
Firestore database
I'm using the following code:
_jobsCollectionReference.snapshots().listen((jobBidsSnapshot) {
if (jobBidsSnapshot.docs.isNotEmpty) {
var jobsWithBids = jobBidsSnapshot.docs
.map((jobBidsSnapshot) =>
JobWithBids.fromMap(jobBidsSnapshot.data(), jobBidsSnapshot.id))
.where((mappedItem) => mappedItem.jobBids != null)
.where((mappedItem) =>
mappedItem.jobBids
.map((e) => e.contractorUserId == loggedInUser.uid)
.toList()
.length >
0)
.toList();
This code results in a list with all objects where the contractorUserId field exists. However, the intention was to only add the documents where the contractorUserId is equal to the Logged in user.
Does anyone know what I'm doing wrong?
You're getting the error because the piece of code below evaluates to true since you're just checking the length of the list even if e.contractorUserId == loggedInUser.uid equals false :
mappedItem.jobBids
.map((e) => e.contractorUserId == loggedInUser.uid)
.toList()
.length >
0
So your code is actually:
var jobsWithBids = jobBidsSnapshot.docs
.map((jobBidsSnapshot) =>JobWithBids.fromMap(jobBidsSnapshot.data(), jobBidsSnapshot.id))
.where((mappedItem) => mappedItem.jobBids != null)
.where((mappedItem) => true) //This is what it evaluates to
.toList();
You should switch map to where in the last check, so it filters any list that does not satisfy the condition. See below:
var jobsWithBids = jobBidsSnapshot.docs
.map((jobBidsSnapshot) =>JobWithBids.fromMap(jobBidsSnapshot.data(), jobBidsSnapshot.id))
.where((mappedItem) => mappedItem.jobBids != null)
.where((mappedItem) => mappedItem.jobBids
.where((e) => e.contractorUserId == loggedInUser.uid)
.toList()
.length > 0
)
.toList();

Lambda expression used inside Include is not valid when using where inside include

User user = await _context.users
.Include(u => u.orders.Where(o => o.Date > startDate && o.Date < enddate))
.Where(u => u.UserID == _auth.User.UserID)
.FirstOrDefaultAsync();
So I have one-to-many relationships between the Users and Orders table, where the user model has a List orders. But I get a 500 server error and "Lambda expression used inside Include is not valid"
I fixed the issue by downloading EF plus, and changing the query to
User user = await _context.users.IncludeFilter(u => u.orders.Where(o => o.Date > startDate && o.Date < enddate)).Where(u => u.UserID == _auth.User.UserID).FirstOrDefaultAsync();

How can i select distinct using one field

How can i select distinct() based on one field?
I have the following LINQ expression, how can I select distinct by ID field. for some reason i used .Distinct() but keeps shown me a duplicate, I want to show just one record
var customersbyName = await _context.vw_CustomerSearch.AsNoTracking()
.Where(c => c.Name.Contains(request.searchWord))
.Distinct()
.ToListAsync();
try:
var customersbyName = await _context.vw_CustomerSearch.AsNoTracking()
.Where(c => c.Name.Contains(request.searchWord))
.Select(c => c.ID)
.Distinct()
.ToListAsync();
Distinct compare each column of the row, so if one column is different, the row is distinct for linq / sql.
You can try it with a GroupBy:
var customersbyName = await _context.vw_CustomerSearch.AsNoTracking()
.Where(c => c.Name.Contains(request.searchWord))
.GroupBy(i => i.ID)
.Select(x => x.First())

LINQ IQueryable Nested Loops

I am trying to replicate this loop as an IQueryable:
foreach (var book in BookList)
{
foreach (var a in book.Authors)
{
if (a.AuthorId.ToString() == Id)
{
AuthorView = new AuthorViewModel(a, item.BookId);
}
}
}
I have tried:
var Test = _context.Book.Include(x => x.Authors)
SelectMany(y => y.Authors).ToList().FirstOrDefault(x => x.AuthorId.ToString() == Id)
.Select(x => new AuthorViewModel(x, ??.BookId);
But I get stuck trying to create the object AuthorViewModel as it requires the BookId that I can no longer access. Is there a way of passing the book Id down?
Sorry, just release the example doesn't make sense.
Books is a table in a database.
Authors is a table in the database which contains many authors.
Book:
BookId
Authors
Authors:
AuthorId
Name
DOB
AuthorList should have been BookList (List). I have corrected this.
I am trying to locate an author based on an author id - and return it in an object (Author, BookId (from the book table))
This is I would do:
var id= int.Parse(Id);
var Test = _context.Book.Include(x => x.Authors)
.SelectMany(item => item.Authors
.Where(y => y.AuthorId == id)
.Select(b => new AuthorViewModel(b,item.BookId));
You can filter and project inside of the SelectMany extension method
I think you don't need SelectMany or Include at all. You can go like;
_context.Book
.Where(b => b.Authors.Any(a => a.AuthorId.ToString() == Id))
.Select(b => new AuthorViewModel(b.Authors.FirstOrDefault(x => x.AuthorId.ToString() == Id), b.BookId);
If you drill down on the Authors (SelectMany) then you have no way to go back to books. The condition on AuthorId needs to be handled internally.
var Test = _context.Book.Include(x => x.Authors)
.FirstOrDefault(x => x.Authors.Any(y => y.AuthorId.ToString() == Id))
.Select(x => new AuthorviewModel(x,x.BookId);
of course this will select only one book per author, just like your code. I wonder if your desired behaviour is to get all books instead...
First of all, convert Id to a number instead of trying to convert AuthorId to a string. Applying any kind of function on a table field means that indexes that cover it can't be used. Instead of a fast search based on an ID, you'll have a full table scan that converts values to strings before comparing them using string semantics. If the Id parameter contains any leading zeros, the comparison will fail.
As for the LINQ query itself, the easiest way is to use the query form. If you want to return one record for each book and author combination, you can write :
var id=int.Parse("ID");
var query= from book in _context.Book
from author in book.Authors
where author.AuthorID = id
select new AuthorViewModel(author,book.BookId);
var records=query.ToList();

How to form a Method based syntax in Linq Entity Framework

Iam using Entity Framework in ASP.NET Web application i have formed an linq Query to fetch the list of offers for the Employee in the location using Query Based syntax . The query is given below.
Main Linq Query
using (var emp = new EmployeeEntities())
{
return
(
from p in emp.Employees
join pl in emp.EmployeeLocations on p.Id equals pl.EmployeeId
join l in emp.OfferLocations on pl.Id equals l.EmployeeLocationId
join po in emp.EmployeeOffers on l.EmployeeOfferId equals po.Id
where p.Id == employeeId && po.ParentId == SpecialGroupId && po.Id == offerid
select po
).ToList().AsReadOnly();
}
I want to know how to form a Method based syntax by using
Where
and
Include
like the below example
Example Linq Query
return emp.EmployeeLocations.Include("OfferLocations.EmployeeOffer.Category").Include("Employee").Where(pl => pl.Id == locationId).ToList<EmployeeLocation>();
Can any one help me to form the method based query.Thank you
To achieve your query couldn't you just do,
using (var emp = new EmployeeEntities())
{
return emp.Where(p => p.Id == employeeId)
.SelectMany(p => p.EmployeeOffers)
.Where(po => po.ParentId == SpecialGroupId && po.Id == offerid)
.ToList()
.AsReadOnly();
}
I found the Answer thank for everyone who helped replying with answers
using (var emp = new EmployeeEntities())
{
var newres = intreat.EmployeeOffers.Where(po => po.OfferLocations.Where(ol => ol.EmployeeLocation.EmployeeId == empId).Any()).Where(pof => pof.ParentId == parentid && pof.Id != empoffer).ToList<EmployeeOffer>();
}

Resources