I'm working on a winforms project
and I have the following linq expressions
LinqQuery =
from t in newContext?.TOURNAMENT_D
from u in newContext.PLAYERS_LIST.Where(b => t.TD_ROWID == b.PL_TOURNAMENT_REFNO).DefaultIfEmpty()
select new
{
t.TD_ROWID,
t.TD_NAME,
t.TD_DATE,
startDate = t.TD_DATE,
endDate = t.TD_DATE,
u.PL_FULLNAME,
u.PL_COUNTRY,
u.PL_REENTRY
};
and the following query is build after the linq query:
SELECT
[Extent1].[TD_ROWID] AS [TD_ROWID],
[Extent1].[TD_NAME] AS [TD_NAME],
[Extent1].[TD_DATE] AS [TD_DATE],
[Extent2].[PL_FULLNAME] AS [PL_FULLNAME],
[Extent2].[PL_COUNTRY] AS [PL_COUNTRY],
[Extent2].[PL_REENTRY] AS [PL_REENTRY]
FROM [dbo].[TOURNAMENT_D] AS [Extent1]
LEFT OUTER JOIN [dbo].[PLAYERS_LIST] AS [Extent2] ON [Extent1].[TD_ROWID] = [Extent2].[PL_TOURNAMENT_REFNO]
I was expecting to see the dates with aliases am I missing something here?
is there a way that I can see the given aliases ?
Thanks!
EDIT:
I was expecting the query to be like
[Extent1].[TD_DATE] AS startDate,
however I can still access that property within the IQueryable
It's very important to realize that LINQ To SQL is not SQL itself. The query that is built is just the optimized query that LINQ To SQL runs on the database to pull the information it needs to pull the data into your C# object.
You should be able to call the following:
LinqQuery.startDate;
or
LinqQuery.endDate;
and those should hold the values that you defined in your select.
Please let me know if I can clarify.
Related
I see several StackOverflow questions on this already but not of them seem to match my scenario. I promise I looked.
I have some queries against my database that I'm using linq to do and I can't figure out why the incorrect SQL is being generated. This is happening in several places in my code. I'm hoping we're just falling into some well known gotcha but I can't wrap my head around why Linq seemingly decides my where clause is dumb and shouldn't add it to the generated SQL query.
Why is this?
Example:
var testing = (from i in context.TableName1 where i.Param1 == object1.GuidParam select i).ToList();
The above query returns the following SQL
{SELECT
[Extent1].[RecordId] AS [RecordId],
[Extent1].[AnotherId] AS [AnotherId],
[Extent1].[YetAnotherId] AS [YetAnotherId],
[Extent1].[WeLikeIds] AS [WeLikeIds],
[Extent1].[WeReallyLikeIds] AS [WeReallyLikeIds]
FROM [dbo].[SomeTable] AS [Extent1]}
However the following query:
var testing = (from i in context.TableName1 where i.Param1 == object1.GuidParam select i);
var testingToList = testing.ToList();
Generates the following correct SQL
{SELECT
[Extent1].[RecordId] AS [RecordId],
[Extent1].[AnotherId] AS [AnotherId],
[Extent1].[YetAnotherId] AS [YetAnotherId],
[Extent1].[WeLikeIds] AS [WeLikeIds],
[Extent1].[WeReallyLikeIds] AS [WeReallyLikeIds]
FROM [dbo].[SomeTable] AS [Extent1]
WHERE [Extent1].[RecordId] = '78e49f5c-0ff8-e311-93f4-00155d514a6d'}
I prefer the lambda notation, and I don't see why this wouldn't work...
var testing = context.TableName1.Where(i => i.Param1 == object1.GuidParam).ToList();
Cleaner, concise and it should work.
I guess it should be really simple, but i cannot find how to do it.
I have a linq query, that selects one column, of type int, and i need it sorted.
var values = (from p in context.Products
where p.LockedSince == null
select Convert.ToInt32(p.SearchColumn3)).Distinct();
values = values.OrderBy(x => x);
SearchColumn3 is op type string, but i only contains integers. So i thought, converting to Int32 and ordering would definitely give me a nice 1,2,3 sorted list of values. But instead, the list stays ordered like it were strings.
199 20 201
Update:
I've done some tests with C# code and LinqPad.
LinqPad generates the following SQL:
SELECT [t2].[value]
FROM (
SELECT DISTINCT [t1].[value]
FROM (
SELECT CONVERT(Int,[t0].[SearchColumn3]) AS [value], [t0].[LockedSince], [t0].[SearchColumn3]
FROM [Product] AS [t0]
) AS [t1]
WHERE ([t1].[LockedSince] IS NULL)
) AS [t2]
ORDER BY [t2].[value]
And my SQL profiler says that my C# code generates this piece of SQL:
SELECT DISTINCT a.[SearchColumn3] AS COL1
FROM [Product] a
WHERE a.[LockedSince] IS NULL
ORDER BY a.[SearchColumn3]
So it look like C# Linq code just omits the Convert.ToInt32.
Can anyone say something useful about this?
[Disclaimer - I work at Telerik]
You can solve this problem with Telerik OpenAccess ORM too. Here is what i would suggest in this case.
var values = (from p in context.Products
where p.LockedSince == null
orderby "cast({0} as integer)".SQL<int>(p.SearchColumn3)
select "cast({0} as integer)".SQL<int>(p.SearchColumn3)).ToList().Distinct();
OpenAccess provides the SQL extension method, which gives you the ability to add some specific sql code to the generated sql statement.
We have started working on improving this behavior.
Thank you for pointing this out.
Regards
Ralph
Same answer as one my other questions, it turns out that the Linq provider i'm using, the one that comes with Telerik OpenAccess ORM does things different than the standard Linq to SQL provider! See the SQL i've posted in my opening post! I totally wasn't expecting something like this, but i seem that the Telerik OpenAccess thing still needs a lot of improvement. So be careful before you start using it. It looks nice, but it has some serious shortcomings.
I can't replicate this problem. But just make sure you're enumerating the collection when you inspect it. How are you checking the result?
values = values.OrderBy(x => x);
foreach (var v in values)
{
Console.WriteLine(v.ToString());
}
Remember, this won't change the order of the records in the database or anywhere else - only the order that you can retrieve them from the values enumeration.
Because your values variable is a result of a Linq expression, so that it doest not really have values until you calling a method such as ToList, ToArray, etc.
Get back to your example, the variable x in OrderBy method, will be treated as p.SearchColumn3 and therefore, it's a string.
To avoid that, you need to let p.SearchColumn3 become integer before OrderBy method.
You should add a let statement in to your code as below:
var values = (from p in context.Products
where p.LockedSince == null
let val = Convert.ToInt32(p.SearchColumn3)
select val).Distinct();
values = values.OrderBy(x => x);
In addition, you can combine order by statement with the first, it will be fine.
I am trying to do a join with a sub query and can't seem to get it. Here is what is looks like working in sql. How do I get to to work in linq?
SELECT po.*, p.PermissionID
FROM PermissibleObjects po
INNER JOIN PermissibleObjects_Permissions po_p ON (po.PermissibleObjectID = po_p.PermissibleObjectID)
INNER JOIN Permissions p ON (po_p.PermissionID = p.PermissionID)
LEFT OUTER JOIN
(
SELECT u_po.PermissionID, u_po.PermissibleObjectID
FROM Users_PermissibleObjects u_po
WHERE u_po.UserID = '2F160457-7355-4B59-861F-9871A45FD166'
) used ON (p.PermissionID = used.PermissionID AND po.PermissibleObjectID = used.PermissibleObjectID)
WHERE used.PermissionID is null
Without seeing your database and data model, it's pretty impossible to offer any real help. But, probably the best way to go is:
download linqpad - http://www.linqpad.net/
create a connection to your database
start with the innermost piece - the subquery with the "where" clause
get each small query working, then join them up. Linqpad will show you the generated SQL, as well as the results, so build your small queries up until they are right
So, basically, split your problem up into smaller pieces. Linqpad is fantastic as it lets you test these things out, and check your results as you go
hope this helps, good luck
Toby
The LINQ translation for your query is suprisingly simple:
from pop in PermissibleObjectPermissions
where !pop.UserPermissibleObjects.Any (
upo => upo.UserID == new Guid ("2F160457-7355-4B59-861F-9871A45FD166"))
select new { pop.PermissibleObject, pop.PermissionID }
In words: "From all object permissions, retrieve those with at least one user-permission whose UserID is 2F160457-7355-4B59-861F-9871A45FD16".
You'll notice that this query uses association properties for navigating relationships - this avoids the need for "joining" and simplfies the query. As a result, the LINQ query is much closer to its description in English than the original SQL query.
The trick, when writing LINQ queries, is to get out of the habit of "transliterating" SQL into LINQ.
I have some linq that returns the correct data.
var numEmails = (from row in EmailBatchProposal
where row.EmailBatchId == emailBatchId
select row.EmailBatchProposalId).Count();
However, if I understand linq correctly, this does not perform optimally. It grabs all the data and then walks through the list and counts the rows. What I'd really like is for linq (in the background) to use like:
Select count(*) from ...
I trust the performance reasons are obvious.
Does anyone know the proper way to do this?
Actually, if the linq query is used with a collection that implements IQueryable and supports translation into underlying SQL variant, it is quite a basic functionality to translate the Count function from your example correctly.
People generally learn best by practicing. I would suggest you get a copy of LinqPad (free), enter in your Linq query, and see what SQL it generates. Then you can modify the Linq query until you get exactly what you want.
Actually, the LINQ-to-SQL is smart enough to know that it should do a count... For example, if I have the following query:
var v = (from u in TblUsers
select u).Count();
the SQL that actually executes when I run this is:
SELECT COUNT(*) AS [value]
FROM [tblUsers] AS [t0]
Amazing, huh? Another poster made the really good suggestion of getting LinqPad - it is a WONDERFUL tool. It will show you the exact SQL that gets executed. You can always confirm with SQL profiler too.
Check the Log of the SQL used in the query.
using (var dbc = new siteDataContext())
{
dbc.Log = Console.Out;
var bd = (from b in dbc.birthdays
select b).Count();
Console.WriteLine("{0}", bd);
}
gives the query:
SELECT COUNT(*) AS [value]
FROM [dbo].[birthdays] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
You can just use the argument of .Count().
int numEmails = EmailBatchProposal.Count(x => x.EmailBatchId == emailBatchId)
As noted below, this doesn't actually resolve to any different SQL, but I think it's at least a cleaner looking alternative.
Does anyone know the equivalent of ISDATE() in LINQ to SQL query syntax? I've got a varchar field in SQL that contains dates and I need to filter out the non-date rows.
was hoping for something like this:
var query = SomeDataContext;
query = from p in query
where p.ISDATE(field1) == true;
select p;
also, how would one cast something for SQL in Linq syntax?
CAST(SomeDate AS SMALLDATETIME)
The trick to doing this is to create a user function in the database which merely calls ISDATE as returns the value
CREATE FUNCTION My_ISDATE(#maybeDate varchar(max))
returns bit
as return ISDATE(#maybeDate);
Then add My_IsDate to you database context, and use it in you query:
var db = SomeDataContext;
var query = from p in db.MyTable
where db.My_ISDATE(p.field1)
select p;
I don't think there is an extension method that maps to ISDATE when using LINQ to SQL.
If you are ok with loading all the data and then doing the filtering in the client space, then use TryParse on the field and compare to the date.
Otherwise, I would create a stored procedure which would return the data you want (so that you can use ISDATE), and then execute that through the context.
Also, your syntax for the use of ISDATE is incorrect. ISDATE just tells you if the expression is a valid date format. Your query would look like this:
var query = SomeDataContext;
query = from p in query
where ISDATE(field1) != 0 && CONVERT(datetime, field1) > some date
select p;
The syntax isn't valid, but it gives you an idea of how to form the query.
A problem with SO is that an increasing number of threads on answers of problems contain outdated answers, mostly because they are not touched in years. However in combination with a search engine (e.g. Google) who then returns as #1 a link (for instance this post) when you query "How should i use IsDate in Linq" it needs someone to then add one answer (at the bottom with 0 votes) of the latest correct answer.
:: https://github.com/dotnet/efcore/issues/8488 >
It now has been added to EF.Functions so you can simply do:
Where(x=> EF.Functions.IsDate(x.somefield))
Looks like you can do it. Links:
http://msdn.microsoft.com/en-us/library/bb386973.aspx
this might be of help but I haven't watched it:
http://mtaulty.com/videos/nuggets/l2s/15_mt_l2s_callingsqlfunctions.wmv
Full list here:
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/05/10/9322.aspx