Linq query to select all numbers that match - c#

I have some difficulties to query a table. In the table there are a column for ResourceID and a column for ProjectID. I want to get a list of all int numbers from the ResourceID where ProjectID match the projId number. Is this possible?
I have tested, but I guess this is wrong. I thought I could get the value by using the resources variable, but that isn't working.
var resources = db.Activities.Where(x => x.ProjectID == projId).ToList();
resources. ????

You could accomplish this via a Select() query to only pull the specific properties that you need (in this case the ResourceID property) for each of the elements within your collection :
// Get your resources that meet your requirement
var resources = db.Activities.Where(x => x.ProjectID == projId).ToList();
// Get your Resource IDs from your previous query
var resourceIds = resources.Select(r => r.ResourceID);
You could actually just perform this in a single call if you preferred :
// This will return a list of ResourceIDs that match
var resourceIds = db.Activities.Where(a => a.ProjectID == projId)
.Select(a => a.ResourceID)
.ToList();

I believe the answer is:
var resources = db.Activities.Where(x => x.ProjectID == projId).Select(x => x.ResourceID).ToList();

You're getting a list of the Activities. What you need to do is to select the item you want--in this case the ResourceID column.
var resources = db.Activities.Where(x => x.ProjectID == projId)
.Select(x => x.ResourceID)
.Distinct() // Thought you might want this
.ToList();
You can also use a different format like this, which can sometimes be clearer.
var resources = (from a in db.Activities
where a.ProjectID == projId
select a.ResourceID).Distinct().ToList();

Please update your query if you want to get list of int..
var resources = db.Activities.Where(x => x.ProjectID == projId).Select(x => x.ResourceID).ToList();

Related

LINQ efficiency

Consider the following LINQ statements:
var model = getModel();
// apptId is passed in, not the order, so get the related order id
var order = (model.getMyData
.Where(x => x.ApptId == apptId)
.Select(y => y.OrderId));
var orderId = 0;
var orderId = order.LastOrDefault();
// see if more than one appt is associated to the order
var apptOrders = (model.getMyData
.Where(x => x.OrderId == orderId)
.Select(y => new { y.OrderId, y.AppointmentsId }));
This code works as expected, but I could not help but think that there is a more efficient way to accomplish the goal ( one call to the db ).
Is there a way to combine the two LINQ statements above into one? For this question please assume I need to use LINQ.
You can use GroupBy method to group all orders by OrderId. After applying LastOrDefault and ToList will give you the same result which you get from above code.
Here is a sample code:
var apptOrders = model.getMyData
.Where(x => x.ApptId == apptId)
.GroupBy(s => s.OrderId)
.LastOrDefault().ToList();
Entity Framework can't translate LastOrDefault, but it can handle Contains with sub-queries, so lookup the OrderId as a query and filter the orders by that:
// apptId is passed in, not the order, so get the related order id
var orderId = model.getMyData
.Where(x => x.ApptId == apptId)
.Select(y => y.OrderId);
// see if more than one appt is associated to the order
var apptOrders = model.getMyData
.Where(a => orderId.Contains(a.OrderId))
.Select(a => a.ApptId);
It seems like this is all you need:
var apptOrders =
model
.getMyData
.Where(x => x.ApptId == apptId)
.Select(y => new { y.OrderId, y.AppointmentsId });

LINQ subquery with multiple columns

I'm trying to recreate this SQL query in LINQ:
SELECT *
FROM Policies
WHERE PolicyID IN(SELECT PolicyID
FROM PolicyRegister
WHERE PolicyRegister.StaffNumber = #CurrentUserStaffNo
AND ( PolicyRegister.IsPolicyAccepted = 0
OR PolicyRegister.IsPolicyAccepted IS NULL ))
Relationship Diagram for the two tables:
Here is my attempt so far:
var staffNumber = GetStaffNumber();
var policyRegisterIds = db.PolicyRegisters
.Where(pr => pr.StaffNumber == staffNumber && (pr.IsPolicyAccepted == false || pr.IsPolicyAccepted == null))
.Select(pr => pr.PolicyID)
.ToList();
var policies = db.Policies.Where(p => p.PolicyID.//Appears in PolicyRegisterIdsList)
I think I'm close, will probably make two lists and use Intersect() somehow but I looked at my code this morning and thought there has to be an easier way to do this,. LINQ is supposed to be a more readble database language right?
Any help provided is greatly appreciated.
Just use Contains:
var policies = db.Policies.Where(p => policyRegisterIds.Contains(p.PolicyID));
Also better store policyRegisterIds as a HashSet<T> instead of a list for search in O(1) instead of O(n) of List<T>:
var policyRegisterIds = new HashSet<IdType>(db.PolicyRegisters......);
But better still is to remove the ToList() and let it all happen as one query in database:
var policyRegisterIds = db.PolicyRegisters.Where(pr => pr.StaffNumber == staffNumber &&
(pr.IsPolicyAccepted == false || pr.IsPolicyAccepted == null));
var policies = db.Policies.Where(p => policyRegisterIds.Any(pr => pr.PolicyID == p.PolicyID));

Get complex object using IN equivalent in LINQ

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.

How to select a single column with Entity Framework?

Is there a way to get the entire contents of a single column using Entity Framework 4? The same like this SQL Query:
SELECT Name FROM MyTable WHERE UserId = 1;
You can use LINQ's .Select() to do that. In your case it would go something like:
string Name = yourDbContext
.MyTable
.Where(u => u.UserId == 1)
.Select(u => u.Name)
.SingleOrDefault(); // This is what actually executes the request and return a response
If you are expecting more than one entry in response, you can use .ToList() instead, to execute the request. Something like this, to get the Name of everyone with age 30:
string[] Names = yourDbContext
.MyTable
.Where(u => u.Age == 30)
.Select(u => u.Name)
.ToList();
I'm a complete noob on Entity but this is how I would do it in theory...
var name = yourDbContext.MyTable.Find(1).Name;
If It's A Primary Key.
-- OR --
var name = yourDbContext.MyTable.SingleOrDefault(mytable => mytable.UserId == 1).Name;
-- OR --
For whole Column:
var names = yourDbContext.MyTable
.Where(mytable => mytable.UserId == 1)
.Select(column => column.Name); //You can '.ToList();' this....
But "oh Geez Rick, What do I know..."
Using LINQ your query should look something like this:
public User GetUser(int userID){
return
(
from p in "MyTable" //(Your Entity Model)
where p.UserID == userID
select p.Name
).SingleOrDefault();
}
Of course to do this you need to have an ADO.Net Entity Model in your solution.
You could use the LINQ select clause and reference the property that relates to your Name column.
If you're fetching a single item only then, you need use select before your FirstOrDefault()/SingleOrDefault(). And you can use anonymous object of the required properties.
var name = dbContext.MyTable.Select(x => new { x.UserId, x.Name }).FirstOrDefault(x => x.UserId == 1)?.Name;
Above query will be converted to this:
Select Top (1) UserId, Name from MyTable where UserId = 1;
For multiple items you can simply chain Select after Where:
var names = dbContext.MyTable.Where(x => x.UserId > 10).Select(x => x.Name);
Use anonymous object inside Select if you need more than one properties.

Chained selects with where at the end

Given following structure: a person has functions. Each function has roles. Each roles has features. Now I would like to figure out with linq if a given person has a certain feature, but I am doing something wrong with this query. As a result I always get the count of the functions (but I'd like to get the count of the features):
var count = person.Functions
.Select(fu => fu.Roles
.Select(r => r.Features
.Where(f => f.FeatureId == 99999)))
.Count();
What am I doing wrong here? According to this query I expect either 0 (hasn't got the feature) or 1.
var query = from function in person.Functions
from role in function.Roles
from feature in role.Features
where feature.FeatureId == 99999
select feature;
var count = query.Count();
or
var count = person.Functions
.SelectMany(function => function.Roles)
.SelectMany(role => role.Features)
.Count(feature => feature.FeatureId == 99999);
If you don't need the exact count but just want to know if the person has the feature or not, use Any instead of Count.
var count = person.Functions
.SelectMany(p => p.Roles)
.SelectMany(r => r.Features)
.Where(f => f.FeatureId == 99999)
.Count();
I'm not really sure, but I think you want the total number of Features with teh given Id. You would want to use SelectMany.

Categories

Resources