How to get the last Item of Database where a Special condition does apply?
var History = (from c in conn.Table<HistoryItem>() select c.Done); //how to get last Item where c.Done is true?
You would need to specify an order condition to have Last make any sense. Otherwise, it would simply be Last() or LastOrDefault() (or you can order in the order direction and take First()
var History = (from c in conn.Table<HistoryItem>() select c.Done)
.OrderByDescending(c => c.DateCreated).FirstOrDefault();
Would select the newest history item. Again, going back to the point about ordering being important.. Whether that's the last or first item is a matter of perspective. It's first if you were to view the change log newest -> oldest, but it's the last in terms of date added.
Related
Im trying to query my OData webservice from a C# application.
When i do the following:
var SecurityDefs = from SD in nav.ICESecurityDefinition.Take(1)
orderby SD.Entry_No descending
select SD;
i get an exception because .top() and .orderby is not supposed to be used together.
I need to get the last record in the dataset and only the last.
The purpose is to get the last used entry number in a ledger and then continue creating new entries incrementing the found entry no.
I cant seem to find anything online that explains how to do this.
Its very important that the service only returns the last record from the feed since speed is paramount in this solution.
i get an exception because .top() and .orderby is not supposed to be used together.
Where did you read that? In general .top() or .Take() should ONLY be used in conjunction WITH .orderby(), otherwise the record being retrieved is not guaranteed to be repeatable or predictable.
Probably the compounding issue here is mixing query and fluent expression syntax, which is valid, but you have to understand the order of precedence.
Your syntax is taking 1 record, then applying a sort order... you might find it easier to start with a query like this:
// build your query
var SecurityDefsQuery = from SD in nav.ICESecurityDefinition
orderby SD.Entry_No descending
select SD;
// Take the first item from the list, if it exists, will be a single record.
var SecurityDefs = SecurityDefsQuery.FirstOrDefault();
// Take an array of only the first record if it exists
var SecurityDefsDeferred = SecurityDefsQuery.Take(1);
This can be executed on a single line using brackets, but you can see how the query is the same in both cases, SecurityDefs in this case is a single ICESecurityDefinition typed record, where as SecurityDefsDeferred is an IQueryable<ICESecurityDefinition> that only has a single record.
If you only need the record itself, you this one liner:
var SecurityDefs = (from SD in nav.ICESecurityDefinition
orderby SD.Entry_No descending
select SD).FirstOrDefault();
You can execute the same query using fluent notation as well:
var SecurityDefs = nav.ICESecurityDefinition.OrderByDescending(sd => sd.Entry_No)
.FirstOrDefault();
In both cases, .Take(1) or .top() is being implemented through .FirstOrDefault(). You have indicated that speed is important, so use .First() or .FirstOrDefault() instead of .Single() or .SingleOrDefault() because the single variants will actually request .Take(2) and will throw an exception if it returns 1 or no results.
The OrDefault variants on both of these queries will not impact the performance of the query itself and should have negligble affect on your code, use the one that is appriate for your logic that uses the returned record and if you need to handle the case when there is no existing record.
If the record being returned has many columns, and you are only interested in the Entry_No column value, then perhaps you should simply query for that specific value itself:
Query expression:
var lastEntryNo = (from SD in nav.ICESecurityDefinition
orderby SD.Entry_No descending
select SD.Entry_No).FirstOrDefault();
Fluent expression:
var lastEntryNo = nav.ICESecurityDefinition.OrderByDescending(sd => sd.Entry_No)
.Select(sd => sd.Entry_No)
.FirstOrDefault();
If Speed is paramount then look at providing a specific custom endpoint on the service to either serve the record or do not process the 'Entry_No` in the client at all, make that the job of the code that receives data from the client and compute it at the time the entries are inserted.
Making the query perform faster is not the silver bullet you might be looking for though, Even if this is highly optimised, your current pattern means that X number of clients could all call the service to get the current value of Entry_No, meaning all of them would start incrementing from the same value.
If you MUST increment the Entry_No from the client then you should look at putting a custom endpoint on the service to simply return the Next Entry_No to use. This should be optimistic meaning that you don't care if the Entry_No actually gets used in the end, but you can implement the end point such that every call will increment the field in the database and return the next value.
Its getting a bit beyond the scope of your initial post, but SQL Server now has support for Sequences that formalise this type of logic from a database and schema point of view, using Sequence simplifies how we can manage these types of incrementations from the client, because we no longer rely on the outcome of data updates to be comitted to the table before the client can increment the next record. (which is what your TOP, Order By Desc solution is trying to do.
What I am trying to achieve.
I am working on a reconcile process and need to ensure my database table has the correct entries. I need to find records in a table that are not in a master list. When I have found these entries I need to group them and find the most recent in each group. If the operation fields of the most recent entries are defined as “Added”, I will need to add additional records with their operation fields marked as “Deleted”, as they are not defined in the master list.
The code I have written selects records in the database that are not in the master list. It then groups these and orders them and finally select the first item in each group which will now be the newest in each group. I then return only the items that have an operation defined as “Added”. I have run this code against my unit tests and with “real” data. Although it works, it is very slow taking maybe forty seconds when run against a database of 16 thousand records (when run from within visual studio). Can anyone advise on if it is possible to modify my code to improve the speed?
Shown below is the code that finds the mismatched records
var linksInDb = _ctx.LinkRecords.ToList();
return (from dbl in linksInDb select dbl)
.Except(
from dbl in linksInDb
from l in links
where dbl.EP1Id == l.Endpoints[0].EntityKey.EntityId && dbl.EP2Id == l.Endpoints[1].EntityKey.EntityId
select dbl)
.GroupBy(x => new {x.EP1Id, x.EP2Id},
(key, g) => g.OrderByDescending(x => x.LastModifiedDate_UTC).First())
.Where(x => x.Operation == "Added")
.ToList();
NB. The master list called "links" is a generic list of type Link which is the same type returned by _ctx.LinkRecords.ToList();
After certain proccess, I wan to remove duplicates from the table and commit the changes, so only single values remain.
I have three criteria for removal:
Name
date
status (is always 1)
So if there are records with same Name, and same date and same status... remove one. Does not matter which one.
I have:
dbContext.tbl_mytable
Since you are talking about deleting records, you need to test this first.
So if there are records with same Name, and same date and same status... remove one. Does not matter which one.
I'm assuming you want to remove all but one, ie, if you have three records with the same details, you remove two and leave one.
If so, you should be able to identify the duplicates by grouping by { Name, date, status} and then selecting all except the first record in each group.
ie something like
var duplicates = (from r in dbContext.tbl_mytable
group r by new { r.Name, r.date, r.status} into results
select results.Skip(1)
).SelectMany(a=>a);
dbContext.tbl_mytable.DeleteAllOnSubmit(duplicates);
dbContext.SubmitChanges();
I have an ordered list of objects. I can easily find an item in the list by using the following code:
purchaseOrders.FirstOrDefault(x => x.OurRef.Equals(lastPurchaseOrder, StringComparison.OrdinalIgnoreCase))
What I want to do is select all the items in the list that appear after this entry. How best to achieve this? Would it to be to get the index of this item and select a range?
It sounds like you want SkipWhile:
var orders = purchaseOrders.SkipWhile(x => !x.OurRef.Equals(...));
Once the iterator has stopped skipping, it doesn't evaluate the predicate for later entries.
Note that that code will include the entry that doesn't match the predicate, i.e. the one with the given reference. It will basically give you all entries from that order onwards. You can always use .Skip(1) if you want to skip that:
// Skip the exact match
var orders = purchaseOrders.SkipWhile(x => !x.OurRef.Equals(...)).Skip(1);
This will be linear, mind you... if the list is ordered by x.OurRef you could find the index with a binary search and take the range from there onwards... but I wouldn't do that unless you find that the simpler code causes you problems.
Probably you should take a look at LINQ's combination of Reverse and TakeWhile methods, if I understand your question correctly.
It may look like purchaseOrder.Reverse().TakeWhile(x => !x.OurRef.Equals(lastPurchaseOrder, StringComparison.OrdinalIgnoreCase)).
Sorry if code is unformatted, I'm from mobile web right now.
May be you want something like this:
int itemIndex = list.IndexOf(list.FirstOrDefault(x => x.OurRef.Equals(lastPurchaseOrder, StringComparison.OrdinalIgnoreCase));
var newList = list.Where((f, i) => i >= itemIndex);
I have two Repeater Control
var list = from i in DA.obm_view_studentLists where i.FranchiseID == FranchiseID && i.ExamDate == DateTime.Parse(this.pallavi.DropDownSelectedValue) select i;
I want to get result in 1 go from database.
this._approvedStudentList.DataSource = list.Select(e => e.ApprovedByOBM == true);
this._pendingStudentList.DataSource = list.Select(e => e.ApprovedByOBM == false);
I have a Label Field (UnPaidTotal) in pendingStudentList Repeater where I want to display Total Fee Pending
I tried but fail
UnPaidTotal = string.Format("{0:c}", list.Select(e => e.ApprovedByOBM == true).Sum(j => j.CourseFee));
Evaluate list to get all results in one shot -- just wrap from i in… select i in parentheses and add .ToList() at the end.
When setting the DataSource, replace list.Select(… with list.Where(…
Same thing when getting the unpaid total -- use Where instead of Select.
You don't need to return two collections from the database, because you're dividing the results based on a boolean value. You want all of the query results, because no matter what each result will belong to one collection or the other, so you can split them in-memory.
Select is used to perform a transformation on a collection, whereas Where is a filter. An example of select would be manufacturerList = carCollection.Select(car => car.Manufacturer);. This takes a collection of cars, and transforms it into an enumerable of Manufacturer, by selecting out just that property from each member of the collection.
The key here is that after your first line of code where you create the query for the list variable you haven't gone out to the database yet. All you did is create an IEnumerable/IQueryable that knows how to go out to the database and get your data. Nothing happens until you actually bind it to a control or otherwise try to iterate over the results.
Your problem is that when you do finally bind to the first control the state of that IEnumerable changes such that it now points to the end of the result set rather than waiting to open the database at the beginning. When you try to bind the second repeater there are no records there.
The easiest way to remedy this is to simply put the original query results in a list, though you should be aware that this will cause your web server to load the entire result set into RAM. Another option is to use one repeater, order the query appropriately and use code to output the desired html depending on what kind of row you have and the extra html between sections. This will perform better but crosses lines between separate tiers.