Get first N Rows from Database using Entity Framework - c#

My process to get first N rows
Get All Data from Database using Entity Framework
var list = new MyDbContext().Set<EntityName>();
Get First N rows using C#
var firstNRows = list.Take(N); // N = int
Suppose,
If N = 2 then I want the first 2 rows of the table but entity give me all rows of the table. Is there any way that entity give me only first N rows from the table not all data from the table?

Actually var list = new MyDbContext().Set<EntityName>(); gets no data at all, it returns a IQueryable<EntityName> which is just a representation of a query of all rows.
When you do var firstNRows = list.Take(N); that also gets no data, that also is a IQueryable<EntityName> which is a representation of a query of the first N rows in the database.
You don't actually get data from the database until you do something like a .ToList()
var firstNRowsList = firstNRows.ToList(); //The database is queried here for the first time.

var awards = await _context.Awards.AsNoTracking()
.OrderBy(x => x.Id)
.Take(15)
.ToListAsync();

Related

How do I select a single grouped column from a dataview?

I have a data table tblWorkList with multiple columns: RecordNr, GroupNum, Section, SubscriberID, and quite a few others.
What I need to do is create a dataview or second datatable that is the equivalent of:
SELECT SubscriberID FROM tblWorkList GROUP BY SubscriberID;
I'm doing it in the application because I need this to end up in a dataview that will then be filtered based on multiple user inputs. I have that part working. I've spent several hours now beating my head against the internet trying to figure out how to do this, but I keep running up against errors in solutions that LOOK like they should work but end up failing spectacularly. Although, that said, I'm VERY inexperienced with LINQ right now, so I'm sure I'm missing something pretty straightforward.
(The basic functionality is this: The table contains a list of records to be processed. Basically, I need to take the table full of records, pull the subscriber IDs into a dataview, allow the user to filter that dataview down by a variety of methods (and providing the user a running count of the number of SubscriberID's matching the selected criteria), and when they're done, assign all of the records associated with the resulting SubscriberID collection to a specific analyst to be processed.)
All of the methods I've attempted to use to create the list or dataview of SubscriberID values are enclosed in this:
using (DataTable dt = dsWorkData.Tables["tblWorkData"])
The table tblWorkData contains approximately 23,000 records.
Here are several of my attempts.
Attempt 1 - Error is
Parameter may not be null. Parameter: source'
var result1 = from row in dt.AsEnumerable()
group row by row.Field<string>("SubscriberID") into grp
select new { SubscriberID = grp.Key };
ShowMessage(result1.Count().ToString());
Attempt 2 - Error is
'Cannot implicitly convert anonymous type: string SubscriberID to DataRow'
EnumerableRowCollection<DataRow> query =
from row in dt.AsEnumerable()
group row by row.Field<string>("SubscriberID") into grp
select new { SubscriberID = grp.Key };
Attempt 3 - Error is
'The [third] name 'row' does not exist in the current context.'
EnumerableRowCollection<DataRow> query2 =
from row in dt.AsEnumerable()
group row by row.Field<string>("SubscriberID") into grp
select row;
Attempt 4 - same error as Attempt 1:
DataTable newDt = dt.AsEnumerable()
.GroupBy(r => new { SubscriberID = r["SubscriberID"] })
.Select(g => g.OrderBy(r => r["SubscriberID"]).First())
.CopyToDataTable();
MessageBox.Show(newDt.Rows.Count.ToString());
Attempt 5 - same error as Attempt 1:
var result = dt.AsEnumerable().GroupBy(row => row.Field<string>("SubscriberID"));
MessageBox.Show(result.Count().ToString());
Attempt 6 - same error as Attempt 1:
var results = dt.AsEnumerable().GroupBy(g => g["SubscriberID"])
.Select(x => x.First());
MessageBox.Show(results.Count().ToString());
So can someone explain what I'm doing wrong here, or at least point me in the right direction? I don't really care WHICH approach gets used, for the record, as long as there's a way to do this.
Answer was a pair of comments from NetMage:
Your SQL query is really using GROUP BY to do DISTINCT, so just use the LINQ Distinct: dt.AsEnumerable().Select(r => r.Field<string>("SubscriberID") ).Distinct().
PS Your first error implies that dt is null - source is the parameter name to AsEnumerable.

EF6 IN clause on specific properties

Good morning,
I'm having trouble with a EF query. This is what i am trying to do.
First i am pulling a list of ID's like so (List of IDs are found in the included x.MappingAccts entity):
Entities.DB1.Mapping mapping = null;
using (var db = new Entities.DB1.DB1Conn())
{
mapping = db.Mappings.Where(x => x.Code == code).Include(x => x.MappingAccts).FirstOrDefault();
}
Later, i'm trying to do a query on a different DB against the list of Id's i pulled above (essentially a IN clause):
using (var db = new Entities.DB2.DB2Conn())
{
var accounts = db.Accounts.Where(mapping.MappingAccts.Any(y => y.Id == ?????????)).ToList();
}
As you can see i only got part way with this.
Basically what i need to do is query the Accounts table against it's ID column and pull all records that match mapping.MappingAccts.Id column.
Most of the examples i am finding explain nicely how to do this against a single dimension array but i'm looking to compare specific columns.
Any assist would be awesome.
Nugs
An IN clause is generated using a IEnumerable.Contains.
From the first DB1 context, materialize the list of Id's
var idList = mapping.MappingAccts.Select(m => m.Id).ToList();
Then in the second context query against the materialized list of id's
var accounts = db.Accounts
.Where(a => idList.Contains(a.Id))
.ToList();
The only problem you may have is with the amount of id's you are getting in the first list. You may hit a limit with the SQL query.
This will give the list of Accounts which have the Ids contained by MappingAccts
using (var db = new Entities.DB2.DB2Conn())
{
var accounts = db.Accounts.Where(s => mapping.MappingAccts.Any(y => y.Id == s.Id)).ToList();
}

detail rows not included query with entity framework 7

I have this query in entity framework 7 that queries a list of invoices, including details rows and customers.
First the data are estracted and after a model class is filled extracting some fields from the invoice, the name of the customer, and the sum of the values from the rows.
var clienti = db.Fatture
.OrderByDescending(cli => cli.DataFattura).ThenByDescending(cli => cli.NumFattura)
.Include(cli => cli.Cliente).Include(cli => cli.Righe)
.Take(recNum)
.ToList();
return clienti.Select( cli => new FatturaVm {
FatturaNo = cli.FatturaNo,
Cliente = cli.Cliente.Descrizione,
Data = cli.DataFattura.Value.ToString("dd/MM/yyyy"),
Importo = cli.Righe.Sum( rg => rg.Importo.Value),
NumeroDocumento = cli.NumFattura.Value + "/" + cli.Anno.Value
}).ToList();
I found a strange thing: if I add the OrderByDescending the invoices are returned with an empty list of the rows, but if I remove the ordering the rows are returned with the details.
Am I missing something?

use items in select query that don't include in Group by

I am using EF6 to develop an application that uses a huge data,so in one of my query
his = db.HISTORies.ToList();
front = db.Fronts.ToList();
warehouses = db.Warehouses.ToList();
//------
var q =
his.GroupBy(j => new { j.Line_Number_PGZ, j.MAT_0_PG,j.JOINT_NO_PGZ }).ToList().Select(m => new gridView()
{
JointNumber = m.Key.JOINT_NO_PGZ,
material0 = m.Key.MAT_0_PGZ,material0Name =his.Where(i=>i.MAT_0_PGZ==m.Key.MAT_0_PGZ).First().Code_0_Object_PGZ,
line = m.Key.Line_Number_PGZ
}).OrderByDescending(i => i.material0Need).ToList();
As you can see i fetch all my database to my application .so in my query i grouped my data based on 2 columns ,but my problem is the his has a lot of records so in this line
his.Where(i=>i.MAT_0_PGZ==m.Key.MAT_0_PGZ).First().Code_0_Object_PGZ
I again search an items in this table and this line makes my application to be so slow how can fix this query?
The Code_0_Object_PGZ is in his list but it can be accessed in the select statement !!!
I want to know how can i access Code_0_Object_PGZ without include it in groupby ?
best regards

LINQ to SQL with a large database table increase performance

I am doing a search on a database table using a wildcard(The contains extension) Here is the code
// This gets a list of the primary key IDs in a table that has 5000+ plus records in it
List<int> ids = context.Where(m => m.name.ToLower().Contains(searchTerm.ToLower())).Select(m => m.Id).ToList();
// Loop through all the ids and get the ones that match in a different table (So basically the FKs..)
foreach (int idin nameId)
{
total.AddRange(context2.Where(x => x.NameID == id).Select(m => m.Id).ToList());
}
In there anything I could change in the LINQ that would result in getting the IDs faster?
Thanks
I have not tested it, but you could do something along these lines:
var total =
from obj2 in context2
join obj1 in context1 on obj2.NameID equals obj1.Id
where obj1.name.ToLower().Contains(searchTerm.ToLower())
select obj2.Id
It joins the two tables, performing a cartesian product first and then limiting it to the pairs where the NameIds match (see this tutorial on the join clause). The where line does the actual filtering.
It should be faster because the whole matching is done in the database, and only the correct ids are returned.
If you had a Name property in the context2 item class that holds a reference to the context1 item, you could write it more readable:
var total = context2
.Where(x => x.Name.name.ToLower().Contains(searchTerm.toLower()))
.Select(x => x.ID);
In this case, Linq to SQL would do the join automatically for you.
In terms of performance you can see tests that show if you search 1 string in 1 000 000 entries its around 100 ms.
Here is the link with tests and implementation.
for (int y = 0; y < sf.Length; y++)
{
c[y] += ss.Where(o => o.Contains(sf[y])).Count();
}

Categories

Resources