Select 'N' rows and get number of rows using Entity Framework - sql-server

Currently we have a page where we need pagination so for that i need 2 info
1. Get total number of rows
2. Fetch 'N' number of rows
Currently i am doing it with 2 query, for step 1 something like
count = db.Transactions
.AsNoTracking()
.Where(whereClause
.Count();
And then
db.Transactions
.AsNoTracking()
.Where(whereClause
.Skip(skipRows)
.Take(pagesize)
.ToList();
Is there is any way to optimize it?

You can try using Local Data:
// Load all Transactions with filtering criteria into the context
db.Transactions.AsNoTracking().Where(whereClause).Load();
// Get Count
var transcationsCount = db.Transactions.Local.Count;
// Paging
var pagedTranscations = db.Transactions.Local.Skip(skipRows).Take(pageSize).ToList();
This should only result in one database query being fired to the database in the initial Load() call.

This will return you an IQueryable and you can do queries against that, each will be executed to the db. This way you don't have to rewrite the query each time you want to query something.
var query = (from t in db.Transactions
where whereClause
select t);
var count = query.Count();
var items = query
.Skip(skipRows)
.Take(pagesize)
.ToList();

Related

Dapper, SqlBuilder extension and Order By descending

I am trying to build a simple query that retrieves data in descending order using Dapper. The database is MySql if that's important.
This is the code I used:
var builder = new SqlBuilder();
var sql = #$"SELECT * FROM table t /**orderby**/ LIMIT #paramSkip, #paramTake";
var template = builder.AddTemplate(sql);
builder.OrderBy("#paramOrderBy DESC", parameters: new
{
paramOrderBy = orderBy,
});
// Limit
builder.AddParameters(parameters: new
{
paramSkip = skip,
paramTake = take
});
return Connection.QueryAsync<TableModel>(
template.RawSql, template.Parameters,
transaction: Transaction
);
This always returns data in ascending order. DESC is just ignored. I tried using the DESC keyword in the query or as parameter but the result was the same.
Only thing that worked was putting order parameters and DESC keyword in query itself (by string interpolation)
(Edit: Typos and text simplification)
You need your query to look something like this:
... ORDER BY <Column name> DESC ...
A column name cannot be parameterized, so you need to insert it into the query something like this:
builder.OrderBy($"{orderBy} DESC");
If your orderBy originates from the user in any way, be sure to sanitize it first to prevent SQL injection. You could - for instance - keep a list of valid column names and validate against it.

How can I use Entity Framework LINQ to find rows where a column starts with a string?

I am currently using this to query data in SQL Server:
var query = db.Phrases.AsQueryable();
if (options.Romaji != null) query = query
.Where(w => w.Romaji.Contains(options.Romaji));
How can I change this so that instead of looking for a row with a column with a string in it that it looks for a row with a column which starts with the string in options.Romaji?
You just need to use the StartsWith() method instead of contains.
query = query.Where(w => w.Romaji.StartsWith(options.Romaji));

Sort a LINQ with another LINQ in MVC

Using SQL Server Management
Using MVC VS 2013 for Web
Being in a Controller
Here materialnumb it's a LINQ query that always return only one value.
Being the following...
var materialnumb = (from r in db.MaterialNumber
where r.MaterialNumber == 80254842
select r.MaterialNumber);
I have another LINQ query from a SQL view that involves several other tables with inner join statements and so on (which includes the previous table db.MaterialNumber) that goes like this:
var query = (from r in db.SQLViewFinalTable
where r.MaterialNumber == Convert.ToInt32(materialnumb.MaterialNumber)
select r
I want to sort all the materials by the retrieved material number from the first query but it drops the following error when I try to pass the query as a model for my View:
LINQ to Entities does not recognize the method 'Int32
ToInt32(System.String)' method, and this method cannot be translated
into a store expression.
I assume this is because the query is an object even if its has just one value so it can't be converted into a single Int32.
Even more, the query it's not being executed, it's just a query...
So, how can achieve my goal?
Additional information: I tried to convert the query outside the "final" query. It still doesn't work.
Additional information: This is just an example, the true query actually has several more other querys embedded and this other querys have also other querys in them, so I need a practical way.
Additional information: I have also tried to convert the query into a string and then again into an int.
Try this:
var materialnumb = (from r in db.MaterialNumber
where r.MaterialNumber == 80254842
select r.MaterialNumber).FirstOrDefault();
var query = from r in db.SQLViewFinalTable
where r.MaterialNumber == materialnumb
select r
But I can not get whay are you filtering by 80254842 and selecting the same value? You can do directly:
var query = from r in db.SQLViewFinalTable
where r.MaterialNumber == 80254842
select r

Using left join instead of union in EF with includeProperties

When I include multiple properties in EF it generates 'UNION ALL' SQL queries to include them. If I have 3 properties to include, it is almost 3 times slower to run it.
If I create the same query with 3 left joins it is performing much better...
Is it possible to use left join instead of union when linq is generating the query?
If it is not possible what is the reason to use union all, which seems slow?
First of all, you can perform left joins in LINQ to entities using DefaultIfEmpty.
Second of all, if your navigation properties are 1:N (and not 1:1 or 1:0..1), then using 3 joins will severely increase the output volume from the database and this will reduce the performance, in this case, running one query to retrieve the main entities, then 3 additional queries based on the IDs from the first query, ran in a single DB call using the .Future() extension, will result in better performance.
E.g.
var entities = context.Entities.AsQueryable().Where(...).ToList();
var ids = entities.select(e => e.Id).ToList();
var subEntities1Query = context.SubEntities1.AsQueryable().Where(se1 =>
ids.Contains(se1.ParentId)).Future();
var subEntities2Query = context.SubEntities2.AsQueryable().Where(se2 =>
ids.Contains(se2.ParentId)).Future();
var subEntities3Query = context.SubEntities3.AsQueryable().Where(se3 =>
ids.Contains(se3.ParentId)).Future();
var subEntities1 = subEntities1Query.ToList();
var subEntities2 = subEntities2Query.ToList();
var subEntities3 = subEntities3Query.ToList();
foreach (var entity in entities)
{
entity.SubEntities1 = subEntities1.Where(se1 =>
se1.ParentId = entity.Id).ToList();
entity.SubEntities2 = subEntities2.Where(se2 =>
se2.ParentId = entity.Id).ToList();
entity.SubEntities3 = subEntities3.Where(se3 =>
se3.ParentId = entity.Id).ToList();
}

How to separate the corresponding column value in the scriptdb query statement in google apps script

While I'm retrieving the values from the scriptdb it returns the entire db while using the below coding.
var db = ScriptDb.getMyDb();
var result = db.query({});
While using the following coding it retrieves the corresponding row fully which satisfies the condition.
var db = ScriptDb.getMyDb();
var result = db.query({p_cost:324});
I want to get the specified column value in the specified row which I retrieved already by using the above coding. Is there any possibility to get the specified column value from the scriptdb? We are write the query in traditional database as follows.
SELECE <COL_NAME> FROM <TABLE_NAME>
Try this:
while(result.hasnext()){
res = result.next();
var p_cost = res.p_cost;
}

Resources