Linq to Entity Select, Exclude 1st result row? - c#

I have a Linq to Entity Select statement that is currently returning all rows from the database. Since the 1st row of data contains header information, is it possible to exclude the first row from the result set?
var surveyProgramType = surveyProgramTypeRepository
.Find()
.OrderBy(x => x.ProgramType);

use .Skip()
var surveyProgramType = surveyProgramTypeRepository
.Find()
.OrderBy(x => x.ProgramType)
.Skip(1);

var surveyProgramType = surveyProgramTypeRepository
.Find()
.OrderBy(x => x.ProgramType).Skip(1);

Related

Order by user and then select max date

I have this LINQ query:
ArrayList arr = new ArrayList();
var data = conn.SCOT_DADOS.OrderByDescending(x => x.DATE)
.GroupBy(r => r.USER)
.ToList();
foreach (var item in data)
{
var itemdata = item.Where(r => r.DATE == item.Max(s => s.DATE));
var name = svc.GetUserName(itemdata.Select(r => r.USER).First().ToString());
var value = itemdata.Select(r => r.VALUE).First();
var date = itemdata.Select(r => r.DATE).First().ToString("dd/MM/yyyy HH:mm:ss");
arr.Add( new{ NAME = name, DATE = date, VALUE = value} );
}
This code will give me the latest result by DATE for each USER.
But the LINQ query is selecting all data from the user and then I'm getting the latest one in the foreach loop.
Is there any way to get only the last data in the LINQ query, so I don't have to take all the user data every time?
I have tried this:
var data = conn.SCOT_DADOS.OrderByDescending(x => x.DATE)
.GroupBy(r => r.USER)
.First()
.ToList();
And then treated item as an object, instead of running selects on it.
It gave me all the data for an individual user, which isn't what I want.
What can be done?
Edit 1:
I get this error if I try to swap OrderByDescending and GroupBy:
Error CS1061 'IGrouping' does not contain a
definition for 'DATE' and no extension method 'DATE' accepting a first
argument of type 'IGrouping' could be found (are
you missing a using directive or an assembly reference?)
Edit 2:
This is some sample data (the column names are not the same because I translated them for the question):
From the data presented, I'd have the results:
If the combination of the (USER, DATE) pair is unique (which seems to be the case when looking at the sample data), the requirement can be trimmed down to
return each record if there is no other record with the same USER and later DATE
which could be translated to the following LINQ query:
var result = conn.SCOT_DADOS
.Where(r => !conn.SCOT_DADOS.Any(r2 => r2.USER == r.USER && r2.Date > r.Date))
// end of Db Query
.AsEnumerable()
.Select(r => new
{
Name = svc.GetUserName(r.User),
Value = r.Value,
Date = r.Date.ToString("dd/MM/yyyy HH:mm:ss")
}).ToList();
I'm a bit confused but from your attempts with First() think you mean this:
conn.SCOT_DADOS.GroupBy(item => item.User)
.Select(grp => grp.OrderByDescending(i => t.Date).First());
This will retrieve for each User only the latest record of it
The reason only swapping the GroupBy and OrderByDescending isn't enough and that you need the Select is that once you grouped that data your enumerable is IEnumerable<IGrouping<User,YourType>>. Each IGrouping is actually a collection by itself so you need to Select only the 1 item you want from it.
Another way is to replace the Select with:
.SelectMany(grp => grp.OrderByDescending(i => t.Date).Take(1))
IMO the first is cleaner, but the second is in the case you need for each user N first items
On the query above you can also add what you have in the foreach loop:
conn.SCOT_DADOS.GroupBy(item => item.User)
.Select(grp => grp.OrderByDescending(i => t.Date).First())
.AsEnumerable()
.Select(item => new {
Name = svc.GetUserName(item.User),
Value = item.Value,
Date = item.Date.ToString("dd/MM/yyyy HH:mm:ss")
}).ToList();
The use of the AsEnumerable() is to invoke the query to be executed to the database before the last Select() which uses the GetUserName method that will not be known to the Oracle database
IMO representing the DateTime as string is not a good way..
Update - The error you get:
Oracle 11.2.0.3.0 does not support apply
It seems that as for this version of Oracle it does not support GroupBy with Select via linq. See Linq to Entities Group By (OUTER APPLY) “oracle 11.2.0.3.0 does not support apply”.
One answer there recommended to create a view in the database for this and then use linq to select over that view. That is what I'd go for
Try this
conn.SCOT_DADOS.GroupBy(x => x.User).Select(x => new
{
User = x.Key,
Date = list.Where(y => y.User == x.Key).Max(y => y.Date)
});

Remove every first element of grouped collection

I have a collection of elements and some of these elements are duplicating. I need to extract all records but only the first record if the record is one of a duplicate set.
I was able to group the elements and find all elements that have duplicates, but how to remove every first element of a group?
var records =
dbContext.Competitors
.GroupBy(x => x.Email)
.Select(x => new { Properties = x,
Count = x.Key.Count() })
.Where(x => x.Count > 1)
.ToList();
EDIT: Seems like it's impossible to accomplish this task with EF, because it fails to translate the desired linq expression to SQL. I'll be happy if someone offer different approach.
To exclude the first record from each email-address group with more than one entry, you could do this:
var records = dbContext.Competitors
.GroupBy(x => x.Email)
.SelectMany(x => (x.Count() == 1) ? x : x.OrderBy(t=>t).Skip(1))
.ToList();
This is the logic :
Group by a property > Select every Group > (Possibly) Sort that > Skip first one
This can be turned into some linq code like this :
//use SelectMany to flat the array
var x = list.GroupBy(g => g.Key).Select(grp => grp.Skip(1)).SelectMany(i => i);

using where clause after get last record?

using (EPOSEntities1 db = new EPOSEntities1())
{
List<ActionPerformed> PLUlist = db.ActionPerformeds.ToList();
ActionPerformed Latest_PLU = PLUlist.OrderByDescending(x => x.Date).FirstOrDefault();
}
This returns the last record stored. However I have now added another column in the table File_Name, how can I add a where clause to this to say orderByDescending to get the latest file, then from there get the first record with the file_Name as 'Sales'.??
so e.g.
File_Name Date
12) Products 11/02/2014
13) Sales 11/02/2014
14) Products 11/02/2014
this would return record 13??
The Where method can filter your collection to only those items where the File_Name is "Sales".
Consider placing your LINQ query before the executing call so that your LINQ-to-DB provider can perform the query server-side and only return you one item. What you were doing is bringing the entire ActionPeformeds table down from the server to the client, then performing the query client-side.
ActionPerformed Latest_PLU = db.ActionPerformeds
.Where(x => x.File_Name == "Sales")
.OrderByDescending(x => x.Date)
.FirstOrDefault();
By "executing call" I mean ToList(), First(), FirstOrDefault(), etc.
Use Where clause before OrderByDescending, if you call ToList it will cause immediate evaluation of the query and records will populated. It will be better if you call Where before evaluation.
ActionPerformed Latest_PLU = db.ActionPerformeds.Where(c=>File_Name == "Sales")
.OrderByDescending(x => x.Date)
.FirstOrDefault();
ActionPerformed Latest_PLU = PLUlist.Where(p => p.File_Name == 'Sales').OrderByDescending(x => x.Date).FirstOrDefault();

Linq Contains in one query

I have a List and i want to write a query about List's ids Contains specific table id.
i Write this and running true but i want to write all in same query..
List<int> tempList=yetkiUygulamaList.Select(y => y.Id).ToList();
query = query.Where(x => tempList.Contains(x.Uygulama.Id));
Wrong Query
query = query.Where(x => yetkiUygulamaList.Select(y =>y.Id).ToList().Contains(x.Uygulama.Id));
this must works
query = query.Where(x => yetkiUygulamaList.Any(y=>y.Id == x.Uygulama.Id));
you can perform a join, it would be more simple and suitable in your case.
If I understand, query is a "collection" of a class (let's call it AObj) containing a property Uygulama and the class Uygulama contains a property Id and yetkiUygulamaList is a "collection" of Uygulama
//will return a IEnumerable<AObj>
IEnumerable<AObj> query = query.Join(yetkiUygulamaList, a => a.Uygulama.Id, u => u.Id, (a,u)=>a);
ToList() materilizes by executing the query, and after that there is no way for NHibernate to understand that the first query should be included as a subquery.
Just remove the useless ToList():
IQueryable<int> tempList = yetkiUygulamaList.Select(y => y.Id); // removed here
query = query.Where(x => tempList.Contains(x.Uygulama.Id));
The above code will generate a single SQL query. If you want to stick it all in one C# code line, just get rid of the intermediary variable:
query = query.Where(x => yetkiUygulamaList.Select(y => y.Id).Contains(x.Uygulama.Id));

Querying A Datable Using Linq Returning Distinct Values

I am attempting to get distinct values from a datatable column. here is my code..
var sourceItems = ds.Tables[0].AsEnumerable()
.GroupBy(x => x.Field<string>("Source").ToString())
.Select(x => x.First());
ddlSource.DataSource = sourceItems;
ddlSource.DataBind();
This code is returning 4 rows of System.Data.DataRow as the values. I need the actual values stored in the rows not the row type. Also is this code a proper way to grab only distinct values in the column?
I would do something like this:
var sourceItems = ds.Tables[0].AsEnumerable()
.Select(x => x.Field<string>("Source"))
.Distinct()
.ToList();
Note that .ToList() can be skipped, but of course it depends on what the DataSource property of the ddlSource object is able to accept. If It's a winforms control I suspect ToList is necessary.
Your code does basically the same as this one, but you must change the last Select into Select(x => x.Key) to select the values that are used to group the rows, and not the first row.
Also your code has more overhead than using Distinct, since GroupBy creates subgroups of the original collection.
Why don't you use the .Distinct extension method?
ds.Tables[0].AsEnumerable()
.Select(x => x.Field<string>("Source").ToString())
.Distinct()
.FirstOrDefault();
How about
var sourceItems = ds.Tables[0].AsEnumerable()
.Select(x => x.Field<string>("Source"))
.Distinct()
.ToList();
ddlSource.DataSource = sourceItems;
ddlSource.DataBind();
(You don't need to call .ToString() on a string, so I've removed that.)

Categories