T-SQL Query
Select * from dbo.User_Users
Where UserID IN (Select UserID from Course_Enrollments)
LINQ to Entities alternative of Above Query
var innerquery = from en in Course_Enrollments
select en.UserID;
var query = from u in User_Users
where innerquery.Contains(u.UserID)
select u;
There are alot of complex subqueries on stackoverflow, i just want to see a simple example of how a simple subquery is done via linq.This is how i done it, however its not good because it sends 2 queries to the database.
Simple answer is use the "let" keyword and generate a sub-query that supports your conditional set for the main entity.
var usersEnrolledInCourses = from u in User_Users
let ces = from ce in Course_Enrollments
select ce.UserID
where ces.Contains(u.UserID)
select u;
This will create an exists block in TSQL similar to
SELECT [Extent1].*
FROM dbo.User_Users AS Extent1
WHERE EXISTS (SELECT 1 AS [C1]
FROM dbo.Course_Enrollements AS Extent2
WHERE (Extent2.UserID = Extent1.UserId))
It's close to what you've asked for and will generally create the same query plan on SQL Server.
Hope this helps!
from u in User_Users
where u.Course_Enrollments.Any()
select u
if you have the foreign keys set up. If not you can do this
from u in User_Users
join cu in Course_Enrollments on u.UserId equals cu.UserId
select u
You also should wrap any of these with .Distinct() call
Related
This Sql query returns the expected data. I need to do the same in EF Query. I am not sure how to do it all in one EF query.
WITH cteproductactions (productkey, actionid) AS (
SELECT productkey, count(*) FROM productactions
GROUP BY productkey
HAVING count(*)>0
)
SELECT p.name,p.productkey,p.imageurl
FROM product p
INNER JOIN cteproductactions c on p.ProductKey=c.productkey
WHERE p.profileid=100
EF Query
var products = productRepo.Where(x => x.profileid=100);
var productkeys = products.Select(x => x.ProductKey).ToList();
var productActions = productActionsRepo.Where(x => productkeys.Contains(x.ProductKey));
You'll tie yourself in knots trying to write an SQL then "converting" it into LINQ or forcing EF to generate an SQL that is the same.. It's better to start from a place where you express what you want in high level (English) and write the LINQ for it; forget the SQL unless there's a real problem
The SQL as written doesn't really make sense, or need a CTE, the HAVING clause is pointless and none of the columns from the CTE are used in the output. The only purpose the CTE serves is to filter the product list down to those that have at least one productkey, so write an EF from that - "all products Where profile is is 100 and a related product key exists" - don't get bogged down in "how do I make EF do a cte?" because these SQL express the same sentiments without a CTE:
SELECT p.name,p.productkey,p.imageurl
FROM product p
INNER JOIN (SELECT DISTINCT productKey FROM productactions) c on p.ProductKey=c.productkey
WHERE p.profileid=100
SELECT DISTINCT p.name,p.productkey,p.imageurl
FROM product p
INNER JOIN productactions c on p.ProductKey=c.productkey
WHERE p.profileid=100
SELECT p.name,p.productkey,p.imageurl
FROM product p
WHERE p.profileid=100
AND EXISTS(SELECT null FROM productactions c WHERE p.ProductKey=c.productkey)
Assuming product and productactions are in a 1:M relationship connected by productKey, consider something like:
var products = productRepo
.Where(p => p.profileid==100 && p.ProductActions.Any())
.Select(p => new {p.Name, p.ProductKey, p.ImageUrl)
Main message here is "don't start from an SQL mindset and think "how can I make EF do this sql", start from a "What do I want and how can I make EF do it" - forget the SQL unless EF is generating something horrifically underperformant.
I am having an issue getting my LINQ query to output as I would like. I am unsure I am taking the right approach.
Tables:
I have two tables Contacts and Permissions with which I perform a LEFT OUTER JOIN.
Join Query:
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()
where (p==null && isAllowed) || (p!=null && /* ... further conditions */))
orderby /* ... ordering removed */
select new { contact, permission = p };
This matches the permissions to a contact where applicable, and null when no matching permission exists.
Desired
I don't wish to have duplicate contacts, I am only interested in the first Contact-Permission record. Like so:
Attempt:
So I assumed that I need to Group By my contact.Id and somehow select FirstOrDefault() on the permissions collection.
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()
where (p==null && isAllowed) || (p!=null && /* ... further conditions */))
orderby /* ... ordering removed */
group p by contact into contactPermissionsGrp
select new { contact = contactPermissionsGrp.Key, permission = contactPermissions.FirstOrDefault() };
Result:
Unfortunately this results in a NotSupportedException: Specific method is not supported.. But I am not sure if my approach is correct or a limitation of the LightSpeed ORM.
Any advise would be appreciated.
Answer question with more questions
Is your query possible in raw SQL in the database you are targeting? If the answer is No then what hope have you of replicating it in LINQ?
I personally don't think that what you are trying to achieve is possible to do via LINQ against MySQL. It would be possible in MS SQL in raw T-SQL by defining an expression and attaching a RANK() column to it then doing a query on that expression.
I feel that your available solutions are:
Find out how to write this query using raw SQL in your native dialect. Lightspeed will let you execute raw SQL and it will even (where you return enough columns) rehydrate that custom query into Entitys (however I don't think that is what you are after in this case).
Give up on reducing the "duplicates" efficiently in the database. Pull the duplicates into memory and then reduce them in memory with LINQ queryies against the IEnumerable set that you get back.
Change your database architecture so you can have a simpler query. Sometimes in situations like this I will find honour in having a column on the Contact table such as "MostSignificantPermssion". That has a number of advantages:
Simpler query to get the Contact and the ONE significant Permission record.
Makes it more obvious to other developers that one of the Permissions has a special significance.
Options!
Appendix - Example of implementing (1) in MS SQL
WITH LastUsagePerPerson AS (
SELECT
ULE.PersonId,
ULE.[Device],
ULE.[AppVersion],
ULE.[CreatedOn],
ROW_NUMBER() OVER(PARTITION BY ULE.PersonId ORDER BY ULE.CreatedOn DESC) AS rk
FROM [dbo].[UsageLogEntry] ULE
)
SELECT
[FirstName]
,[LastName]
,[EmailAddress]
,[EmailAddressUnverified]
,[MobileNumber]
,[MobileNumberUnverified]
,[LastDeviceUsed] = LastUsagePerPerson.Device
,[LastAppVersion] = LastUsagePerPerson.AppVersion
,[LastDeviceUsage] = LastUsagePerPerson.CreatedOn
,[LastLoggedInOn]
FROM [dbo].[Person] P
LEFT JOIN LastUsagePerPerson ON P.Id = LastUsagePerPerson.PersonId
WHERE rk = 1
ORDER BY [Id]
I don't know what Lightspeed can or can't. Try to simplify you LINQ Query
In EF i would do something like this.
from c in Contacts
let p = (from p in permission where p.ObjectId == c.Id select p).FirstOrDefault()
select new { ContactID = c.Id,
Name = c.Name,
Permission = p.PermissionId,
Permitted = p.Permitted};
I have understood what you are trying to get and I have solved your problem,just follow the below code what I did...
select * from contacts as a
left join permissions as b
on a.ContactId = b.ContactId
group by a.ContactId ;
I have got the requeried result using the above code which you were trying to get.Just try that,your problem will be solved.
Using EF DB first I have two entities (Supplier, Product) that have a many-to-many relationship. Entity Framework does not create an entity for the associated table (SupplierProduct) as the associated table contains only the primary keys of the strong entities.
I have been getting all Suppliers that do not supply a given product with the following query:
var q1 = context.Suppliers.Where(s=>!s.Products.Any(p=>p.Id == 1));
The SQL produced uses an EXISTS dependent subquery similar to this:
SELECT *
FROM Suppliers s
WHERE NOT EXISTS
(SELECT 1
FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)
Is it possible, using Linq to Entities method syntax, to produce a query that uses joins on the associated table instead?
ie:
SELECT DISTINCT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId != 1
Update
As pointed out by JoeEnos my queries above don't do the same thing. The NOT EXISTS subquery is probably the best way to go here. What if I was trying to get all suppliers who did supply a product? I would change my linq to entities query slightly to:
var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));
And the SQL generated would be:
SELECT *
FROM Suppliers s
WHERE EXISTS
(SELECT 1
FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)
Which is fine, I get the result I want. However if I was writing SQL in this case I would normally do:
SELECT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId = 1
Can my linq to entities query be changed to produce the above SQL?
To generate SQL where a join is used instead of EXISTS when selecting an entity based on its m:n association with another entity SelectMany() can be used. Eg:
var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));
Can be rewritten to:
var q1 = context.Products.Where(p => p.Id == 1).SelectMany(p => p.Suppliers);
Your two queries do very different things. Your Any/EXISTS query gets suppliers who do not have product 1 at all. Your JOIN query gets all suppliers who have any products other than 1, regardless of whether or not they also have product 1.
I don't think you can do what you're looking for with just a JOIN and WHERE - you can do it with an IN clause, but I think the EXISTS query is the most correct way of looking for your data.
In any case, one of the wonderful things about Entity Framework is that you don't have to worry about what gets generated - as long as the LINQ statement is ok, then it will find the best way of writing the query, and you should never have to look at it. That's especially true when you do paging and other things like that, where the LINQ is simple, but the generated SQL is horribly ugly.
Using C# and ASP.NET, I need my gridview to draw columns from multiple tables. How do I do this? I currently have
`SelectCommand="SELECT [SubId], [CustName], [CustCity] FROM [Customer]">
</asp:SqlDataSource>`
as my select statement, but I need to select from two more tables. What is the syntax?
apologies for being unclear before.
Your SelectCommand should be the same statement that you would execute if you were running the query on the database directly. So, in your case, you would want something like:
SELECT [SubId], [CustName], [BroName], [Entity]
FROM [Customer]
JOIN [Broker] ON <join condition>
JOIN [Submission] ON <join condition>
If you don't need to update the SqlDataSource, you can simply put JOINS into your query.
For example:-
Select CustFld1, CustFld2, OrdFld1, OrdFld2 from Cust inner join Ord on CustPKeyFld=OrdCustFKeyField
If you do need to update the SqlDataSource, you need to use sub-queries to return the data that would otherwise be returned in the join
For example:-
Select CustFld1, CustFld2, (Select OrdFld1 from Ord where OrdCustFkeyFld=CustPKeyFld) as OrdFld1, (Select OrdFld2 from Ord where OrdCustFKeyFld=CustPKeyFld) as OrdFld2 from Cust
I have an application in which I am using a stored procedure and LINQ.
My procedure looks like this:
myProc
select col1, Col2, Col3 from Tab1 inner join Tab2 on col1=ColA join tab3 on Col1=ColD
Select cola, Colb, Colc from Taba inner join Tabb on cola=ColX join tabc on Cola=ColY
Select colP, ColQ, ColR from TabP inner join TabQ on colP=ColW join tabR on ColP=ColZ
I am executing this stored procedure in LINQ.
When I execute it I am getting the results in IMultipleResults.
Below is my code in LINQ:
[Function(Name = "dbo.MyProc")]
[ResultType(typeof(TabA))]
[ResultType(typeof(TabB))] .....
public IMultipleResults GetMultipleResults([Parameter(DbType = "VarChar(50)")] string i_Cola)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), i_Cola);
return (IMultipleResults)result.ReturnValue;
}
When I execute it as follows:
MyContext mCtx = new MyContext()
var allResult = mCtx.GetMultipleResults(txtName.Text.Trim());
IEnumerable<Taba> TabaRes = allResult.GetResult<Taba>();
IEnumerable<TabB> TabbRes = allResult.GetResult<Tabb>();
I am getting the column values of tables but I want the Inner Joined columns also.
I've referred to many blogs and forums, such as...
Ben Hall's Blog
Guy Burstein's Blog
Microsoft's Blog
... to try to find a solution to my problem, but couldn't find any.
well better to use views in respect to SP(If u are not able to write a linq to sql query),if u are using Linq to Sql its worthLess to use Sp becoze it decrease the performance.and one more thing if u are using Linq to sql there is no Need to use any type of join if ur data base is completely normalized.
If still ur prob is not solved just show me the table structure and what the out u need i will write a query for u...
I am not sure I understand your need, but can you change the proc to return * or all the columns in all the tables you need?
If the stored procedure isn't returning the data required then the only option for LINQ would be for it to go query the database again itself.
This would mostly negate the point of having a stored procedure and be slower than just adding the required parameters to your stored procedure.
Maybe this would be a stupid question, but in your store procedure:
select col1, Col2, Col3 from Tab1
inner join Tab2 on col1=ColA join
tab3 on Col1=ColD
col1,col2,col3 are all from tab1, but you never did a select from the other tables that you are trying to do inner join. Did you tried
select col1,col2,col3,colA,colB...
-or-
select * from...