How to write good LINQ query for this? - asp.net-mvc-3

I have a LINQ Query. When i run the query it takes so much of time to perform the operation. How can i modify the query to perform good. here is the LINQ query.
Query
var model = (from items in Db.Items
where items.ItemNo == DD.ItemNumber
select new ViewModel()
{
INo = items.ItemNo,
BTags = (from asd in Db.BibContents where asd.BibId == items.BibId && asd.TagNo == "245" && asd.Sfld == "a" select asd.Value).FirstOrDefault(),
Sid = (from stat in Db.ItemStatus1 where stat.Id == items.StatusId select stat.Description).FirstOrDefault(),
Option = DD.Option
}).ToList();

You should analyze the query in SQL Profiler and Query Analyzer. The problem is probably indexes on your tables.

First of all, while your query is always working with database objects, you'd better do all your job in SQL and bring only the results to LINQ.
This will probably improve your performance.

Make sure EF is not causing a Select N+1 problem.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/08/18/select-n-1-problem-how-to-decrease-your-orm-performance.aspx

Related

LINQ very SLOW when making .toList()

I'm with a problem i can't solve,
I'm making a simple query in linq:
List<MOV> mvs = (from x in new MyAppDataContextSingleton().DataContext.MOV
where x.dateMOV.GetValueOrDefault(x.dateCriation).Date >= initialDate.Date && x.dateMOV.GetValueOrDefault(x.dateCriation).Date <= finalDATE.Date
orderby x.dateMOV
select x).ToList();
Execute this query directly on SQL is very fast, it only return about 20 results!
When i execute this query on my project using LINQ is very very slow taking more that 20 seconds :\ but this problem only happens when executing the query to this table. Any idea about what's happening? and how can i solve it?
Best regards,
André
Try turning off Deferred Loading:
db.DeferredLoadingEnabled = false;
http://msdn.microsoft.com/en-us/library/Bb386920(v=vs.100).aspx

(Fluent)NHibernate SELECT IN

Given the following tables:
tool
*toolid
*n other fields
process
*processid
*n other fields
toolprocess
*toolprocessid
*toolid
*processid
*n other fields
When trying to select all tools for a specific process I get up to a few thousand selects on toolprocess where my Linq looks like this:
from tool in tools
where toolprocesses.Any(t=>t.Tool.Id==tool.Id)
select tool
where toolprocesses contains the list of toolprocesses with the same processid
In SQL I would just write
SELECT * FROM TOOL WHERE toolid IN
(SELECT TOOLID FROM TOOLPROCESS WHERE processid = 'someid');
It takes almost no time and works as expected
How can I get NHibernate to create this query (or something similar)?
I don't know if you can do it in Query, but you can do it in QueryOver / Criteria.
In QueryOver it would look like:
var subQuery = QueryOver.Of<Toolprocess>()
.Where(x => x.Process.Id == id)
.Select(x => x.Tool.Id);
var result = session.QueryOver<Tool>()
.WithSubquery.WhereProperty(x => x.Id).In(subQuery)
.List();
http://www.philliphaydon.com/2010/09/28/queryover-with-nhibernate-3-lovin-it/
Alternatively, if you want to do Exists rather than In, I've blogged about it here:
http://www.philliphaydon.com/2011/01/19/revisiting-exists-in-nhibernate-3-0-and-queryover/
Try
from t in Session.Query<Tool>()
join tp in Session.Query<Toolprocess>() on t equals tp.Tool
where tp.Process.Id == 'someid'
select t;
I assume that you're using NH 3.X. This should be even faster than the Select...Where...In query.

Longish LINQ query breakes SQLite-parser - simplify?

I'm programming a search for a SQLite-database using C# and LINQ.
The idea of the search is, that you can provide one or more keywords, any of which must be contained in any of several column-entries for that row to be added to the results.
The implementation consists of several linq-queries which are all put together by union. More keywords and columns that have to be considered result in a more complicated query that way. This can lead to SQL-code, which is to long for the SQLite-parser.
Here is some sample code to illustrate:
IQueryable<Reference> query = null;
if (searchAuthor)
foreach (string w in words)
{
string word = w;
var result = from r in _dbConnection.GetTable<Reference>()
where r.ReferenceAuthor.Any(a => a.Person.LastName.Contains(word) || a.Person.FirstName.Contains(word))
orderby r.Title
select r;
query = query == null ? result : query.Union(result);
}
if (searchTitle)
foreach (string word in words)
{
var result = from r in _dbConnection.GetTable<Reference>()
where r.Title.Contains(word)
orderby r.Title
select r;
query = query == null ? result : query.Union(result);
}
//...
Is there a way to structure the query in a way that results in more compact SQL?
I tried to force the creation of smaller SQL-statments by calling GetEnumerator() on the query after every loop. But apparently Union() doesn't operate on data, but on the underlying LINQ/SQL statement, so I was generating to long statements regardless.
The only solution I can think of right now, is to really gather the data after every "sub-query" and doing a union on the actual data and not in the statement. Any ideas?
For something like that, you might want to use a PredicateBuilder, as shown in the chosen answer to this question.

complex orderby that links to another table

I have the following query to start with:
var query = from p in db.Products
from pc in p.NpProductCategories
where pc.CategoryId == categoryId
select p;
I'm applying some more filtering on it and in the end I want to sort the results:
if (orderBy == ProductSortingEnum.Name)
query = query.OrderBy(x => x.Name);
else
query = query.OrderBy(............);
My big problem (coming from not knowing linq too good) is the ELSE here. How can I sort results by a column that is not in the current result set? I would like to somehow link to another linq query in the orderby. The sorting I'm trying to achive is to link to NpProductVariants query using the ProductId to match between NpProductVariant and Products
and sort by the Price of the NpProductVariant
Assuming you have the relationship set up in the dbml...
For one to one (and many to one):
query = query.OrderBy(p => p.NpProductVariant.Price);
For one to many:
query = query.OrderBy(p => p.NpProductVariants.Select(v => v.Price).Max());
Also:
var query =
from p in db.Products
where p.NpProductCategories.Any(pc => pc.CategoryId == categoryId)
select p;
I think you can hook your Join to your query as long as it is returning the same thing. So maybe something like (I'm not 100 % sure since I haven't tried it):
query = from i1 in query
join i2 in query2 on i1.PropertyToJoin equals i2.PropertyToJoin
orderby i1.OrderProp1, i2.OrderProp2
select i1;
But I think it might be a good idea to check the generated sql so it is still effective.

Linq filter collection with EF

I'm trying to get Entity Framework to select an object and filter its collection at the same time. I have a JobSeries object which has a collection of jobs, what I need to do is select a jobseries by ID and filter all the jobs by SendDate but I can't believe how difficult this simple query is!
This is the basic query which works:
var q = from c in KnowledgeStoreEntities.JobSeries
.Include("Jobs.Company")
.Include("Jobs.Status")
.Include("Category")
.Include("Category1")
where c.Id == jobSeriesId
select c;
Any help would be appreciated, I've been trying to find something in google and what I want to do is here:http://blogs.msdn.com/bethmassi/archive/2009/07/16/filtering-entity-framework-collections-in-master-detail-forms.aspx
It's in VB.NET though and I couldn't convert it to C#.
EDIT: I've tried this now and it doesn't work!:
var q = from c in KnowledgeStoreEntities.JobSeries
.Include("Jobs")
.Include("Jobs.Company")
.Include("Jobs.Status")
.Include("Category")
.Include("Category1")
where (c.Id == jobSeriesId & c.Jobs.Any(J => J.ArtworkId == "13"))
select c;
Thanks
Dan
Include can introduce performance problems. Lazy loading is guaranteed to introduce performance problems. Projection is cheap and easy:
var q = from c in KnowledgeStoreEntities.JobSeries
where c.Id == jobSeriesId
select new
{
SeriesName = c.Name,
Jobs = from j in c.Jobs
where j.SendDate == sendDate
select new
{
Name = j.Name
}
CategoryName = c.Category.Name
};
Obviously, I'm guessing at the names. But note:
Filtering works.
SQL is much simpler.
No untyped strings anywhere.
You always get the data you need, without having to specify it in two places (Include and elsewhere).
No bandwith penalties for retrieving columns you don't need.
Free performance boost in EF 4.
The key is to think in LINQ, rather than in SQL or in materializing entire entities for no good reason as you would with older ORMs.
I've long given up on .Include() and implemented Lazy loading for Entity Framework

Resources