I have the following query in SQL :
SELECT TOP 1 *
FROM sessions
ORDER BY start_time
How should I code it instead in LINQ-to-SQL
Use OrderBy for the ordering, and First or possibly FirstOrDefault for the equivalent of TOP 1:
var session = db.Sessions.OrderBy(x => x.StartTime).FirstOrDefault();
if (session != null)
{
// Use the session
}
else
{
// There weren't any sessions
}
You could use a query expression for the first part, but it seems pretty pointless - it would end up being more long-winded than using "dot notation", so I'd stick to that.
(from i in dc.sessions
orderby i.start_time).Take(1);
or
dc.sessions.OrderBy(x => x.start_time).Take(1);
Here's an example:
NorthwindDataContext db = new NorthwindDataContext();
var shippers = from shipper in db.Shippers
orderby shipper.CompanyName
select shipper;
return shippers.First();
However, using the syntax recommended by Jon Skeet above is probably most appropriate for your simple use case.
Related
In a project I have to maintain, I have this Linq query using Take(1) :
(from workflow in db.Workflows
from search in db.Searches.Where(p => p.WorkflowId == workflow.WorkflowId).Take(1).DefaultIfEmpty()
select new { workflow, hasSearch = search.SearchId > 0 }).ToList();
When Take(1) is translated to SQL, it gives something like :
ROW_NUMBER() OVER(PARTITION BY WorkflowId ORDER BY WorkflowId)
which occurs to be lacking performance.
I guess the developer had a SELECT TOP 1 in mind. But if use FirstOrDefault it would not return an IQueryable anymore. So, my question is : how can I rewrite the Linq query to keep the same purpose and not using Take, if possible ?
If understand correctly needed result, query should be rewritten in this way:
var query =
from workflow in db.Workflows
select new
{
workflow,
hasSearch = db.Searches.Any(p => p.WorkflowId == workflow.WorkflowId)
};
I have a query which is fully translatable to SQL. For unknown reasons LINQ decides the last Select() to execute in .NET (not in the database), which causes to run a lot of additional SQL queries (per each item) against database.
Actually, I found a 'strange' way to force the full translation to SQL:
I have a query (this is a really simplified version, which still does not work as expected):
MainCategories.Select(e => new
{
PlacementId = e.CatalogPlacementId,
Translation = Translations.Select(t => new
{
Name = t.Name,
// ...
}).FirstOrDefault()
})
It will generates a lot of SQL queries:
SELECT [t0].[CatalogPlacementId] AS [PlacementId]
FROM [dbo].[MainCategories] AS [t0]
SELECT TOP (1) [t0].[Name]
FROM [dbo].[Translations] AS [t0]
SELECT TOP (1) [t0].[Name]
FROM [dbo].[Translations] AS [t0]
...
However, if I append another Select() which just copies all members:
.Select(e => new
{
PlacementId = e.PlacementId,
Translation = new
{
Name = e.Translation.Name,
// ...
}
})
It will compile it into a single SQL statement:
SELECT [t0].[CatalogPlacementId] AS [PlacementId], (
SELECT [t2].[Name]
FROM (
SELECT TOP (1) [t1].[Name]
FROM [dbo].[Translations] AS [t1]
) AS [t2]
) AS [Name]
FROM [dbo].[MainCategories] AS [t0]
Any clues why? How to force the LINQ to SQL to generate a single query more generically (without the second copying Select())?
NOTE: I've updated to query to make it really simple.
PS: Only, idea I get is to post-process/transform queries with similar patterns (to add the another Select()).
When you call SingleOrDefault in MyQuery, you are executing the query at that point which is loading the results into the client.
SingleOrDefault returns IEnumerable<T> which is no longer an IQueryable<T>. You have coerced it at this point which will do all further processing on the client - it can no longer perform SQL composition.
Not entirely sure what is going on, but I find the way you wrote this query pretty 'strange'. I would write it like this, and suspect this will work:
var q = from e in MainCategories
let t = Translations.Where(t => t.Name == "MainCategory"
&& t.RowKey == e.Id
&& t.Language.Code == "en-US").SingleOrDefault()
select new TranslatedEntity<Category>
{
Entity = e,
Translation = new TranslationDef
{
Language = t.Language.Code,
Name = t.Name,
Xml = t.Xml
}
};
I always try to separate the from part (selection of the datasources) from the select part (projection to your target type. I find it also easier to read/understand, and it generally also works better with most linq providers.
You can write the query as follows to get the desired result:
MainCategories.Select(e => new
{
PlacementId = e.CatalogPlacementId,
TranslationName = Translations.FirstOrDefault().Name,
})
As far as i'm aware, it's due to how LINQ projects the query. I think when it see's the nested Select, it will not project that into multiple sub-queries, as essentially that would be what would be needed, as IIRC you cannot use multiple return columns from a sub-query in SQL, so LINQ changes this to a query-per-row. FirstOrDefault with a column accessor seems to be a direct translation to what would happen in SQL and therefore LINQ-SQL knows it can write a sub-query.
The second Select must project the query similar to how I have written it above. It would be hard to confirm without digging into a reflector. Generally, if I need to select many columns, I would use a let statement like below:
from e in MainCategories
let translation = Translations.FirstOrDefault()
select new
{
PlacementId = e.CatalogPlacementId,
Translation = new {
translation.Name,
}
})
I use asp.net 4, ef 4 and c#, LINQ and Non-Equijoins.
Here below I wrote two examples of Non-Equijoins.
Both are working fine in my model.
Because I'm pretty new to Linq, I would like ask you:
Which syntax typology would you advice me to adopt in my code?
Which code performance faster?
Thanks for your help:
Here some useful links:
http://msdn.microsoft.com/en-us/library/bb882533.aspx
http://msdn.microsoft.com/en-us/library/bb311040.aspx
http://msdn.microsoft.com/en-us/library/bb310804.aspx
// Query sintax
var queryContents =
from cnt in context.CmsContents
let cntA =
from a in context.CmsContentsAssignedToes
select a.CmsContent.ContentId
where cntA.Contains(cnt.ContentId) == false
select cnt;
// Query method
var queryContents02 =
from c in context.CmsContents
where !(
from a in context.CmsContentsAssignedToes
select a.ContentId).Contains(c.ContentId)
select c;
I'd prompt for a third option:
var validContentIds = from a in context.CmsContentsAssignedToes
select a.ContentId;
var queryContents = from cnt in context.CmsContents
where !validContentIds.Contains(cnt.ContentId)
select cnt;
Or alternatively (and equivalently):
var validIds = context.CmsContentsAssignedToes.Select(a => a.ContentId);
var queryContents = context.CmsContents
.Where(cnt => !validIds.Contains(cnt.ContentId));
I wouldn't expect the performance to be impacted - I'd expect all of these to end up with the same SQL.
I like the first query syntax (it is better readable for me but this part of question is subjective) and I think the perforamance will be the same because queries are actually the same. let keyword just stores subexpression to variable but generated SQL query should be the "same".
How can I implement the following SQL query as linq to entities query?
select *, MIN(QueuedDate)
from pcm_transactions
where QueuedDate IS NOT NULL And ExecutionDate IS NULL
group by SimId
I spent hours thinking and trying varius methods - hope to find the right answer here.
EDIT:
Here is one of my first tries:
// Get the oldest queued action
var queuedTransactions =
(from t in db.TransactionSet
where t.QueuedDate.HasValue && !t.ExecutionDate.HasValue
group t by new { t.TransactionId, t.QueuedDate } into tr
select new
{
Transaction = db.TransactionSet.First(q => q.TransactionId == tr.Key.TransactionId),
QueuedDate = tr.Min(m => m.QueuedDate)
}).ToList();
One problem is that the SQL isn't valid to start with; You have to
group by every column that is not an aggregate expression (eg. min/max
etc), so "select *" simply doesn't make sense. Do you have sample data
and required results to help us rewrite this into Linq?
– Quoted from Will's comment
I have a LINQ statement where I'd like to merge in the First address with the Nickname of 'Me'.
using (var ctx = new DataEntities())
{
return from c in ctx.Customers.Include("Addresses")
let m = from a in c.Addresses where a.Nickname == "Me" select a
where m.Any()
select new
{
Id = c.CustomerId,
m.First().Name,
m.First().Address1,
m.First().Address2,
m.First().City,
m.First().State,
m.First().Zip,
m.First().Email,
m.First().PhoneNumber
};
}
I'm wondering:
Is it going to hurt performance if I call First multiple times like this?
Is there an better LINQ statement for this?
Just also realized, Do I need to .Include("Addresses")?
For LINQ to SQL, EF, etc, it probably won't matter - it is entirely possible that the TSQL translation will make it identical anyway. Of course, you can profile to be sure ;-p
But for LINQ-to-Objects (which is very literal) it will. You can improve this by using let:
return from c in ctx.Customers.Include("Addresses")
let m = from a in c.Addresses where a.Nickname == "Me" select a
where m.Any()
let first = m.First()
select new
{
Id = c.CustomerId,
first.Name,
first.Address1,
...
first.PhoneNumber
};