Linq - Orderby by ID Value - c#

I have the following linq:
objfl = db.tblFl.First(t => t.sp == id && t.ProgID == sPgm);
I like to also order by id but not sure how to do this. I tried a number of different ways but was not successful

As suggested by BrokenGlass, if you want to filter by ProgID, sort by sp and retrieve the first item:
db.tblFl.Where(t => t.ProgID == sPgm)
.OrderBy(t => t.sp)
.First()

Try this
objfl = db.tblFl.Where(t => t.sp == id && t.ProgID == sPgm).OrderBy(t => t.sp);

Related

Using two Linq query in a single method

As shown in the below code, the API will hit the database two times to perform two Linq Query. Can't I perform the action which I shown below by hitting the database only once?
var IsMailIdAlreadyExist = _Context.UserProfile.Any(e => e.Email == myModelUserProfile.Email);
var IsUserNameAlreadyExist = _Context.UserProfile.Any(x => x.Username == myModelUserProfile.Username);
In order to make one request to database you could first filter for only relevant values and then check again for specific values in the query result:
var selection = _Context.UserProfile
.Where(e => e.Email == myModelUserProfile.Email || e.Username == myModelUserProfile.Username)
.ToList();
var IsMailIdAlreadyExist = selection.Any(x => x.Email == myModelUserProfile.Email);
var IsUserNameAlreadyExist = selection.Any(x => x.Username == myModelUserProfile.Username);
The .ToList() call here will execute the query on database once and return relevant values
Start with
var matches = _Context
.UserProfile
.Where(e => e.Email == myModelUserProfile.Email)
.Select(e => false)
.Take(1)
.Concat(
_Context
.UserProfile
.Where(x => x.Username == myModelUserProfile.Username)
.Select(e => true)
.Take(1)
).ToList();
This gets enough information to distinguish between the four possibilities (no match, email match, username match, both match) with a single query that doesn't return more than two rows at most, and doesn't retrieve unused information. Hence about as small as such a query can be.
With this done:
bool isMailIdAlreadyExist = matches.Any(m => !m);
bool isUserNameAlreadyExist = matches.LastOrDefault();
It's possible with a little hack, which is grouping by a constant:
var presenceData = _Context.UserProfile.GroupBy(x => 0)
.Select(g => new
{
IsMailIdAlreadyExist = g.Any(x => x.Email == myModelUserProfile.Email),
IsUserNameAlreadyExist = g.Any(x => x.Username == myModelUserProfile.Username),
}).First();
The grouping gives you access to 1 group containing all UserProfiles that you can access as often as you want in one query.
Not that I would recommend it just like that. The code is not self-explanatory and to me it seems a premature optimization.
You can do it all in one line, using ValueTuple and LINQ's .Aggregate() method:
(IsMailIdAlreadyExist, IsUserNameAlreadyExist) = _context.UserProfile.Aggregate((Email:false, Username:false), (n, o) => (n.Email || (o.Email == myModelUserProfile.Email ? true : false), n.Username || (o.Username == myModelUserProfile.Username ? true : false)));

How to select a list of distinct values based on some values using linq or entity

I want to get all the Pre_Number where all Reconcile_Status related to that Pre_Number=null. In this case there should not be any item in list.If there would be some other Pre_number for eg. 7/2018 and it has two records and Reconcile_Status for those records is NULL then i should get one item in list that is 7/2018.
I tried
var NoNReconciled = context.tbl_prerelease_invoice
.Where(x => x.Reconcile_Status==null)
.Select(y => new { y.Pre_number }).Distinct().ToList();
But i got 6/2018
Well, your current attempt only checks that there is at least one record where Reconcile_Status is null, but it doesn't check that there are no records with the same Pre_number where Reconcile_Status is not null.
This should do the trick:
var NoNReconciled = context.tbl_prerelease_invoice
.Where(x => x.Reconcile_Status == null &&
!context.tbl_prerelease_invoice
.Any(y => y.Pre_number == x.Pre_number && y.Reconcile_Status != null)
).Select(y => new { y.Pre_number })
.Distinct().ToList();
No need to create anonymous object for Pre_Number. Try below code
var NoNReconciled = context.tbl_prerelease_invoice
.Where(x => x.Reconcile_Status==null)
.Select(y => y.Pre_number).Distinct().ToList();
Try this-
context.tbl_prerelease_invoice.GroupBy(r => r.Pre_number).Where(kv => kv.All(r => r.Reconcile_Status==null)).Select(kv => kv.Key).ToList();

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 find minimum value in a collection using linq?

I have a collection where i need to find an item with lowest price if more than 1 found the by default any should be selected and it's isPriceSelected property need to set false.
I am trying something like this.
lstBtn.Where(p => p.CategoryID == btnObj.CategoryID &&
p.IsSelected == true && p.IsPriceApplied == true)
.ToList()
.Min(m=>m.Price)
Just the select the property that you want the minimum from:
var minimumPrice = lstBtn
.Where(p => p.CategoryID == btnObj.CategoryID && p.IsSelected && p.IsPriceApplied)
.Min(p => p.Price);
If you actually want to find the item with the lowest price you need to order the collection:
var itemWithMinimumPrice = lstBtn
.OrderBy(p => p.Price)
.FirstOrDefault(p => p.CategoryID == btnObj.CategoryID && p.IsSelected && p.IsPriceApplied);
or this, could be more efficient:
var itemWithMinimumPrice = lstBtn
.Where(p => p.CategoryID == btnObj.CategoryID && p.IsSelected && p.IsPriceApplied)
.OrderBy(p => p.Price)
.FirstOrDefault();
Enumerable.FirstOrDefault returns one item or null if no item matches the predicate.
You can try something like this:
var result = lstBtn
.Where(p => p.CategoryID == btnObj.CategoryID && p.IsSelected && p.IsPriceApplied)
.OrderBy(p => p.Price)
.First();
This will first find all items which have the specified CategoryID, IsSelected, and IsPriceApplied all set to true, then sort items by Price, and return the first item with the lowest price.
Out of the box, linq can only return the actual value with Min and Max methods.
You can use a good project morelinq https://code.google.com/p/morelinq/wiki/OperatorsOverview
It has the method you need. For myself, I find this project having too many methods, so I simply cut and paste only needed from its sources.
With morelinq your code should look like:
lstBtn.Where(p => p.CategoryID == btnObj.CategoryID && p.IsSelected == true && p.IsPriceApplied==true).MinBy(m=>m.Price)
Another approach, if you also need to get all duplicates:
var lowestPriceProducts = lstBtn.Where(p => p.CategoryID == btnObj.CategoryID)
.GroupBy(p => p.Price, new { p.Price, Product = p})
.OrderByDescending(x => x.Price)
.First()
.Select(x => x.Product)
.ToList()
This query will return you a list (with only one item if there are no duplicate prices) of products with minimal price. Then you can do anything with it.

How to use Linq Contains()?

I am using nHibernate and I need to create a query that does this:
Course Table
CourseId
CourseName
Task Table // course can have many tasks
TaskName
TaskId
CousreId
Now I need to do a contains:
session
.Query<Course>()
.Where(x =>
x.Tasks.Contains(/* wants a task object. I want to do it on property level. */) &&
x.CourseId == 1)
How can I change my query to do a Contains on TaskName?
Project your Tasks to a TaskName then use contains on that.
var query = session
.Query<Course>()
.Where(x => x.Tasks
.Select(t => t.TaskName)
.Contains(myTaskName)
&& x.CourseId == 1);
If I correctly understood you can use Any method
session.Query<Course>().Where(x => x.Tasks.Any(t => t.Name == "task name")
&& x.CourseId == 1);
Have you tried this?
var results = session.Query<Course>()
.Where(crs => crs.Tasks.Count(tsk => tsk.TaskName == theName) > 0);
This should count the number of tasks with the correct name (specified in theName in my example), and return all courses that have a count value greater than zero, i.e. all courses that contain a task with the specific name.
You either have to implement your own IComparer or IEqualityComparer (as I recall, I may be off) and base it on a specific property of the object. Or use Count() or Find() instead. Here's some pseudo code:
session.Query<Course>().Where(x => x.Tasks.Count(t => t.TaskProperty == "something") > 0 && x.CourseId == 1)
I would try something like this:
var results = session
.Query<Course>()
.Where(crs => crs.Tasks.Any(tsk => tsk.TaskName == theName) && crs.CourseId == 1);

Categories

Resources