I have a list of vehicles that are in various categories..
public IList<Vehicle> GetAllByCat(int compId, short catId)
{
var _vehicles = Context.Vehicle
.Where(i =>
i.CompanyId == compId &&
i.VehicleCategories.Any(o => o.VehicleCategoryId == catId))
.ToList();
return _vehicles;
}
But it returns null (and I get an text in debug that _vehicles does not exists in current Context)
I have searched extensively for an answer but not found anything that helps.
Any idea?
You have to get the VehicleCategories first then you can use Any method on it. so one way would be using eager loading to get the related categories then search within them.
public IList<Vehicle> GetAllByCat(int compId, short catId)
{
var _vehicles = Context.Vehicle
.Include(x => x.VehicleCategories)
.Where(i =>
i.CompanyId == compId &&
i.VehicleCategories.Any(o => o.VehicleCategoryId == catId))
.ToList();
return _vehicles;
}
Related
I have used this to pick just a single column from the collection but it doesn't and throws casting error.
ClientsDAL ClientsDAL = new DAL.ClientsDAL();
var clientsCollection= ClientsDAL.GetClientsCollection();
var projectNum = clientsCollection.Where(p => p.ID == edit.Clients_ID).Select(p => p.ProjectNo).ToString();
Method:
public IEnumerable<Clients> GetClientsCollection(string name = "")
{
IEnumerable<Clients> ClientsCollection;
var query = uow.ClientsRepository.GetQueryable().AsQueryable();
if (!string.IsNullOrEmpty(name))
{
query = query.Where(x => x.Name.Contains(name));
}
ClientsCollection = (IEnumerable<Clients>)query;
return ClientsCollection;
}
As DevilSuichiro said in comments you should not cast to IEnumerable<T> just call .AsEnumerable() it will keep laziness.
But in your case it looks like you do not need that at all because First or FirstOrDefault work with IQueryable too.
To get a single field use this code
clientsCollection
.Where(p => p.ID == edit.Clients_ID)
.Select(p => p.ProjectNo)
.First() // if you sure that at least one item exists
Or (more safe)
var projectNum = clientsCollection
.Where(p => p.ID == edit.Clients_ID)
.Select(p => (int?)p.ProjectNo)
.FirstOrDefault();
if (projectNum != null)
{
// you find that number
}
else
{
// there is no item with such edit.Clients_ID
}
Or even simpler with null propagation
var projectNum = clientsCollection
.FirstOrDefault(p => p.ID == edit.Clients_ID)?.ProjectNo;
What is wrong in this query? It's about 2 entities that can be logically deleted by inserting a delete date. So I must be sure I get a single Entity with is collection of SubEntities. All with DateDelete not null.
return DbContext.Entity
.AsNoTracking()
.Include(y => y.SubEntities.Select(sb => sb.DateDelete == null))
.Single(y => y.Name == entityName && y.DateDelete == null);
On runtime I get an exception
The Include path expression must refer to a navigation property
defined on the type. Use dotted paths for reference navigation
properties and the Select operator for collection navigation
properties. Parameter name: path
I also tried this with same error
return DbContext.Entity
.AsNoTracking()
.Include(y => y.SubEntities.Where(sb => sb.DateDelete == null))
.Single(y => y.Name == entityName && y.DateDelete == null);
After my own investigation I found it is impossible to filter on .Include() but there are workarounds by using .Select() method or the filter library.
Workaround 1
return DbContext.Entity
.AsNoTracking()
.Where(e => e.DateDelete == null)
.Select(e => new
{
e.Id,
e.Property,
e.DateDelete,
SubEntities = e.SubEntities.Where(se => se.DateDelete == null)
})
.ToList();
Workaround 2
The solution given by Gert Arnold here with EntityFramework.DynamicFilters. This workaround has some limitation. Read the documentation.
I have a list of type customer. I need to insert all values of the list in the database before checking if a customer with the same customer number exists for that particular client.
For that I am firing a query to get me all customers who are there in the database having customer number equal to ones in the list. The query I am writing is not working, here's the code.
CustomerRepository.Find(x => x.ClientId == clientId)
.Where(x => x.CustomerNumber.Contains(lstCustomersInserted.Select(c => c.CustomerNumber)));
Keep it simple:
var lstCustomerNumbers = lstCustomersInserted.Select(c => c.CustomerNumber);
var res = CustomerRepository.Where(x => x.ClientId == clientId && lstCustomerNumbers.Any(c => c == x.CustomerNumber));
I think you have it backwards. Try reversing the Contains.
Edit: I switched to using the generic predicate Exists instead of Contains based on the comment, so you can match a property.
CustomerRepository.Find(x => x.ClientId == clientId)
.Where(x => lstCustomersInserted.Exists(c => x.CustomerNumber == c.CustomerNumber));
How about an Except?
CustomerRepository.Select(x => x.ClientID)
.Except(lstCustomersInserted.Select(x => x.CustomerID));
This will return the IDs of the objects in the repo that don't exist in your lstCustomersInserted.
I am using nHibernate to retrieve a collection of orders (and its order lines) from a Sql Server database.
This is my ShipmentOrder class:
public class ShipmentOrder
{
private ICollection<ShipmentDetail> _ShipmentsDetails;
public virtual ReadOnlyCollection<ShipmentDetail> ShipmentsDetails
{
get { return (new List<ShipmentDetail>(_ShipmentsDetails).AsReadOnly()); }
}
}
nHibernate returns a IList with all the details (ShipmentsDetails) loaded (since I Eager load them).
Now, I would like to filter my collection of ShipmentOrder and ShipmentDetail and get back a collection of ShipmentDetail.
I've tried something like this:
IList<ShipmentOrder> Results;
// Fetch orders using nHibernate
Results = FetchOrders();
var shipmentLines = Results
.Where(x => x.Company == "XXX" && x.OrderNumber == "111")
.SelectMany(x => x.ShipmentsDetails)
.Where(s => s.RowNumber == 1 && s.RowSeq == 0)
.ToList();
But I've realized that I obtain multiple results of the same line.
I've converted the lamda expression like this:
var shipmentLines = Results
.Where(x => x.Company == "XXX" && x.OrderNumber == "111")
.SelectMany(x => x.ShipmentsDetails)
.Where(s => s.RowNumber == 1 && s.RowSeq == 0)
.Distinct()
.ToList();
and it works fine.
I was wondering if there's a better way to achieve the same result without the distinct.
UPDATE:
I am using SelectMany here cause this is the only way I've found to apply filters to children (ShipmentsDetails).
this looks like Linq2Objects, therefor the IList Results contains duplicate records, probably you do eager fetching to levels deep which unfortunatly results in duplicate root entities. use distinctrootentity-resulttransformer in the query
I have this search method:
public List<Employeees> AutoSuggestEmployeee(string keyword,
long employeeeTypeId, int count)
{
return context.Employeees.Where(
x => x.EmployeeeName.Contains(keyword)
&& x.EmployeeeTypeId == employeeeTypeId)
.Take(count).ToList();
}
I have another collection of Employeees, say "BadEmployeees", what I want is using the same previous method to return all Employeees except "BadEmployeees".
I tried to write it like this:
return context.Employeees.Where(
x => x.EmployeeeName.Contains(keyword)
&& x.EmployeeeTypeId == employeeeTypeId)
.Except(BadEmployeees).Take(count).ToList();
But it is giving an exception that Except can just work with data types such as Int, Guid,...
The Except method does a comparison, so it has to know how to compare the objects. For simple types there are standard comparisons, but for complex types you need to supply an equality comparer that compares the relevant data in the object.
Example:
class EmployeeComparer : IEqualityComparer<Employeees> {
public bool Equals(Employeees x, Employeees y) {
return x.Id == y.Id;
}
public int GetHashCode(Employeees employee) {
return employee.Id.GetHashCode();
}
}
Usage:
return
context.Employeees
.Where(x => x.EmployeeeName.Contains(keyword) && x.EmployeeeTypeId == employeeeTypeId)
.Except(BadEmployeees, new EmployeeComparer())
.Take(count)
.ToList();
If you're happy to retrieve all the data and then perform the "except", that's relatively easy:
return context.Employees
.Where(x => x.EmployeeName.Contains(keyword)
&& x.EmployeeTypeId == employeeeTypeId)
// Limit the data *somewhat*
.Take(count + BadEmployees.Count)
// Do the rest of the query in-process
.AsEnumerable()
.Except(BadEmployees)
.Take(count)
.ToList();
Alternatively:
// I'm making some assumptions about property names here...
var badEmployeeIds = badEmployees.Select(x => x.EmployeeId)
.ToList();
return context.Employees
.Where(x => x.EmployeeName.Contains(keyword)
&& x.EmployeeTypeId == employeeeTypeId)
&& !badEmployeeIds.Contains(x.EmployeeId))
.Take(count)
.ToList();