I have 3 objects that I need to link together
Parent: TblClients
This will have multiple children of Type TblBusinessLeads , the key between the two is ClientID
Type Lead will have multiple children of type TblFeeBreakouts , the key between the two is LeadID
I have written the following LINQ to get the databack, but it is not coming back (out of memory exception)
from t0 in TblClients
join t1 in TblBusinessLeads on t0.ClientID equals t1.ClientID into t1_join
from t1 in t1_join.DefaultIfEmpty()
join t3 in TblFeeBreakouts on t1.LeadID equals t3.LeadID into t3_join
from t3 in t3_join.DefaultIfEmpty()
orderby
t0.ClientID,
t1.LeadID
select new {
client_data = t0,
business_lead_data = t1_join,
fee_breakout_data = t3_join
}
I am not sure of you can even do this, but the idea seems pretty common. Any help would be greatly appreciated. Thanks
EDIT:
Wow lot of comments. Here goes my answers
I am trying to run the query in LinqPad, thats where the Out of Memory is Occuring
If I look at the SQL generated, it gives me
SELECT [t0].[ClientID], [t0].[ClientName], [t0].[ClientDesc], [t0].[EditedBy], [t0].[EditedDate], [t0].[CreatedBy], [t0].[CreatedDate], [t3].[LeadID], [t3].[InitiativeName], [t3].[Description], [t3].[NewBusNeeds], [t3].[CreativeNeeds], [t3].[IdeationNeeds], [t3].[Comments], [t3].[LossReasons], [t3].[OriginDate], [t3].[DateReceivedAssignment], [t3].[DueDate], [t3].[TimelineNotes], [t3].[PendingCode], [t3].[EstStartDate], [t3].[EstEndDate], [t3].[ExeStartDate], [t3].[ExeEndDate], [t3].[Probable80Total], [t3].[Possible50Total], [t3].[Emerging25Total], [t3].[NoBudget0Total], [t3].[TotalBudget], [t3].[FinancialNotes], [t3].[DollarsRecordFor], [t3].[BizDevContactUserID], [t3].[BizDevContact2UserID], [t3].[SVPContactUserID], [t3].[ClientMgmtContactUserID], [t3].[CMAdditionalContactUserID], [t3].[AdditionalContactUserID], [t3].[CreatorUserID], [t3].[OfficeID], [t3].[ClientID] AS [ClientID2], [t3].[LeadTypeID], [t3].[ActionNeeded], [t3].[ActionDate], [t3].[NewBusDeliveryDate], [t3].[NewBusDesc], [t3].[CreativeDeliveryDate], [t3].[CreativeDesc], [t3].[IdeationDeliveryDate], [t3].[IdeationDesc], [t3].[AltMediaDeliveryDate], [t3].[AltMediaDesc], [t3].[MobileOpsDeliveryDate], [t3].[MobileOpsDesc], [t3].[EventsDeliveryDate], [t3].[EventsDesc], [t3].[Routing], [t3].[RoutingDate], [t3].[Deleted], [t3].[LeadSourceID], [t3].[NatureofLeadID], [t3].[NatureofLeadNotes], [t3].[EditedBy] AS [EditedBy2], [t3].[EditedDate] AS [EditedDate2], [t3].[CreatedBy] AS [CreatedBy2], [t3].[CreatedDate] AS [CreatedDate2], [t3].[ClientContactName], [t3].[ClientContactTitle], [t3].[ReportingYear], (
SELECT COUNT(*)
FROM [tblBusinessLead] AS [t4]
WHERE [t0].[ClientID] = [t4].[ClientID]
) AS [value], [t1].[LeadID] AS [LeadID2]
FROM [tblClient] AS [t0]
LEFT OUTER JOIN [tblBusinessLead] AS [t1] ON [t0].[ClientID] = [t1].[ClientID]
LEFT OUTER JOIN [tblFeeBreakout] AS [t2] ON [t1].[LeadID] = [t2].[LeadID]
LEFT OUTER JOIN [tblBusinessLead] AS [t3] ON [t0].[ClientID] = [t3].[ClientID]
ORDER BY [t0].[ClientID], [t1].[LeadID], [t2].[LeadID], [t2].[FeeTypeID], [t3]. [LeadID]
This returns like 1.2 million rows
There is no mapping in the model becuase the DB has no relationships (they are inferred, no foreign keys or anything like that)
The reason I am using t1_join and t3_join is because if I use t1 or t3, I get the single entity, not the IEnumerable of the object, hence I cant loop over it.
If you have more questions, please ask.
First of all, what possible use could a client have for 1.2 million rows? There is no real good use case for this, so your first step should be figuring out how to filter your results appropriately.
Second, I believe the reason your query is returning OutOfMemoryException is because LinQPad is doing a ToList() or something similar so that I can show the results of the query in the bottom pane. The ToList() is loading all 1.2 million rows into memory. If you ran the query in a regular .Net app, the following will return an IQueryable<> which will not load into memory.
var query =
from t0 in TblClients
join t1 in TblBusinessLeads on t0.ClientID equals t1.ClientID into t1_join
from t1 in t1_join.DefaultIfEmpty()
join t3 in TblFeeBreakouts on t1.LeadID equals t3.LeadID into t3_join
from t3 in t3_join.DefaultIfEmpty()
orderby
t0.ClientID,
t1.LeadID
select new {
client_data = t0,
business_lead_data = t1_join,
fee_breakout_data = t3_join
};
As stated above, it is probably a good idea to setup asociations on these tables, which I did... The LINQ for the result after the association was simple
var clientList = (from a in tblClients
select a).ToList();
From there it was just accessing the properties.
Related
I'm using SqlKata in my project and it's necessary to connect several tables with the help of nested join. I expect to see something like that:
SELECT * FROM t1
LEFT JOIN (t2 LEFT JOIN t3 ON t3.id = t2.id)
ON t2.id = t1.id
In Join/LeftJoin/RigthJoin methods, I did not find any overloads that would accept anything other than a join or other request.
Wouldn't want to manually make such connections, maybe someone has already faced such a problem? That would be great, I would really appreciate a hint.
Defining JOIN precedence is not available in SqlKata at the moment.
But you can achieve same result by using a Sub Query.
var query = new Query("t1")
.LeftJoin(
new Query("t2").LeftJoin("t3", "t3.id", "t2.id").As("tmp"),
j => j.On( "tmp.id", "t1.id")
);
This query would result in the following sql:
SELECT * FROM [t1] LEFT JOIN (
SELECT * FROM [t2] LEFT JOIN [t3] ON [t3].[id] = [t2].[id]
) AS [tmp] ON ([tmp].[id] = [t1].[id])
I'm a junior developer and trying to convert the following linq statement to T-SQL:
var items = from u in DataContext.Users_SearchUsers(searchPara.UserFirstName,
searchPara.UserLastName,
searchPara.UserEmailAddress,
fetchOptions.page,
fetchOptions.rp,
fetchOptions.sortname,
fetchOptions.sortorder)
.ToList()
join a in DataContext.UserAccesses
.Where(x => x.Access.AccessTypeId == 4).ToList() on u.UserID equals a.UserId into accessGroup
select new {};
Can one please help me ? into accessGroup ---> (very important)
First of all you need to understand where your data is coming from. You are loading information from Users_SearchUsers on the one hand and UserAccesses on the other hand. The first query looks like
select <somecolumns>
from users
where <somefilters>;
(you need to use your actual columns and criteria, but Users_SearchUsers is not specified in the question at all). I have ignored paging here for the sake of simplicity
The second query looks like this:
select *
from user_accesses
where access_type_id = 4;
Let's join the two:
select <someoutercolumns>
from
(
select <someinnercolumns>
from users
where <somefilters>
) t1
join
(
select <someotherinnercolumns>
from user_accesses
where access_type_id = 4
) t2
on t1.user_id = t2.user_id;
These queries are probably not the exact solutions you need, but you want the answers to improve, then improve your question.
The requirement makes sense if the LINQ query is very slow. In that case you will need to refactor it in the following manner:
select <somecolumns>
from users
join user_accesses
on users.user_id = user_accesses.user_id and user_accesses.access_type_id = 4
where <somefilters>;
you can use this code
select *(you can put your columns instead *)
from Users
join UserAccesses
on Users.userid = UserAccesses.userid
where UserAccesses.typeid = 4;
What the difference between writing a join using 2 from clauses and a where like this:
var SomeQuery = from a in MyDC.Table1
from b in MyDC.Table2
where a.SomeCol1 == SomeParameter && a.SomeCol2 === b.SomeCol1
and writing a join using the join operator.
This is for a join on 2 tables but of course, sometimes, we need to join even more tables and we need to combine other from clauses with where if we choose the syntax above.
I know both syntax queries return the same data but I was wondering if there's a performance difference, or another kind of difference, that would conclusively favor one syntax over the other.
Thanks for your suggestions.
This question is actually answered pretty good in these two.
INNER JOIN ON vs WHERE clause
INNER JOIN vs multiple table names in "FROM"
I've included two examples on how three different LINQ expressions will be translated into SQL.
Implicit join:
from prod in Articles
from kat in MainGroups
where kat.MainGroupNo == prod.MainGroupNo
select new { kat.Name, prod.ArticleNo }
Will be translated into
SELECT [t1].[Name], [t0].[ArticleNo]
FROM [dbo].[Article] AS [t0], [dbo].[MainGroup] AS [t1]
WHERE [t1].[MainGroupNo] = [t0].[MainGroupNo]
Inner join:
from prod in Articles
join kat in MainGroups on prod.MainGroupNo equals kat.MainGroupNo
select new { kat.Name, prod.ArticleNo }
Will be translated into
SELECT [t1].[Name], [t0].[ArticleNo]
FROM [dbo].[Article] AS [t0]
INNER JOIN [dbo].[MainGroup] AS [t1] ON [t0].[MainGroupNo] = [t1].[MainGroupNo]
Left outer join:
from prod in Articles
join g1 in MainGroups on prod.MainGroupNo equals g1.MainGroupNo into prodGroup
from kat in prodGroup.DefaultIfEmpty()
select new { kat.Name, prod.ArticleNo }
Will be translated into
SELECT [t1].[Name] AS [Name], [t0].[ArticleNo]
FROM [dbo].[Article] AS [t0]
LEFT OUTER JOIN [dbo].[MainGroup] AS [t1] ON [t0].[MainGroupNo] = [t1].[MainGroupNo]
If you want to test how your expressions will be translated into SQL, I recommend that you try LINQPad. It's an awesome tool for figuring out this kind of stuff.
var result = from a in DB.classA
from b in DB.classB
where a.id.Equals(b.id)
select new{a.b};
I want to have following type of query in entity frame work
SELECT c2.*
FROM Category c1 INNER JOIN Category c2
ON c1.CategoryID = c2.ParentCategoryID
WHERE c1.ParentCategoryID is NULL
How to do the above work in Entity framework...
Well, I don't know much about EF, but that looks something like:
var query = from c1 in db.Category
where c1.ParentCategoryId == null
join c2 in db.Category on c1.CategoryId equals c2.ParentCategoryId
select c2;
Just to tidy this up the following is a bit nicer and does the same thing:
var query = from c1 in db.Category
from c2 in db.Category
where c1.ParentCategoryId == null
where c1.CategoryId == c2.ParentCategoryId
select c2;
In EF 4.0+, LEFT JOIN syntax is a little different and presents a crazy quirk:
var query = from c1 in db.Category
join c2 in db.Category on c1.CategoryID equals c2.ParentCategoryID
into ChildCategory
from cc in ChildCategory.DefaultIfEmpty()
select new CategoryObject
{
CategoryID = c1.CategoryID,
ChildName = cc.CategoryName
}
If you capture the execution of this query in SQL Server Profiler, you will see that it does indeed perform a LEFT OUTER JOIN. HOWEVER, if you have multiple LEFT JOIN ("Group Join") clauses in your Linq-to-Entity query, I have found that the self-join clause MAY actually execute as in INNER JOIN - EVEN IF THE ABOVE SYNTAX IS USED!
The resolution to that? As crazy and, according to MS, wrong as it sounds, I resolved this by changing the order of the join clauses. If the self-referencing LEFT JOIN clause was the 1st Linq Group Join, SQL Profiler reported an INNER JOIN. If the self-referencing LEFT JOIN clause was the LAST Linq Group Join, SQL Profiler reported an LEFT JOIN.
Is it possible to accomplish something like this using linqtosql?
select * from table t1
left outer join table2 t2 on t2.foreignKeyID=t1.id
left outer join table3 t3 on t3.foreignKeyID=t1.id
I can make it work using both DataLoad options or join syntax. But the problem is whenever I add a second left join, linqtosql queries with MULTIPLE sql statements, instead of doing a second left join in the underlying sql.
So a query like the one above will result in dozens of sql calls instead of one sql call with 2 left joins.
What are my other options? I can use a view in the DB, but now I'm responsible for creating the hierarchy from the flattened list, which is one of the reasons to use an ORM in the first place.
Note that T2 and T3 are 1:M relationships with T1. Is it possible to have linq efficiently query these and return the hierarchy?
I don't think this is likely to be the right solution to your problem because there are more than one many to one relationships to your parent entity table:
select * from table t1
left outer join table2 t2 on t2.foreignKeyID = t1.id
left outer join table3 t3 on t3.foreignKeyID = t1.id
This is like a person with multiple children and multiple vehicles:
Say t1 is the person
id str
1 Me
Say t2 are the children
PK foreignKeyID str
A 1 Boy
B 1 Girl
Say t3 are the vehicles
PK foreignKeyID str
A 1 Ferrari
B 1 Porsche
Your result set is:
Me Boy Ferrari
Me Girl Ferrari
Me Boy Porsche
Me Girl Porcshe
Which I fail to see how this is a useful query (even in SQL).
Here is a similar question. Be cognizant of how the joins are composed.
For example, the following Linq to Sql query on AdventureWorks:
AdventureWorksDataContext db = new AdventureWorksDataContext();
var productStuff = from p in db.Products
join pl in db.ProductListPriceHistories on p.ProductID equals pl.ProductID into plv
from x in plv.DefaultIfEmpty()
join pi in db.ProductInventories on p.ProductID equals pi.ProductID into pii
from y in pii.DefaultIfEmpty()
where p.ProductID == 764
select new { p.ProductID, x.StartDate, x.EndDate, x.ListPrice, y.LocationID, y.Quantity };
Yielded the same SQL (verified via Profiler) as this SQL query:
SELECT Production.Product.ProductID,
Production.ProductListPriceHistory.StartDate,
Production.ProductListPriceHistory.EndDate,
Production.ProductListPriceHistory.ListPrice,
Production.ProductInventory.LocationID,
Production.ProductInventory.Quantity
FROM Production.Product
LEFT OUTER JOIN Production.ProductListPriceHistory ON Production.Product.ProductID = Production.ProductListPriceHistory.ProductID
LEFT OUTER JOIN Production.ProductInventory ON Production.Product.ProductID = Production.ProductInventory.ProductID
WHERE Production.Product.ProductID = 764
Multiple LEFT JOINs on the Primary Key of the parent table, yielding one generated SQL query.
I would think LINQ to SQL would be able to translate your left outer joins as long as you put the DefaultIfEmpty() calls in the right places:
var q = from t1 in table
join t2 in table2 on t1.id equals t2.foreignKeyID into j2
from t2 in j2.DefaultIfEmpty()
join t3 in table3 on t1.id equals t3.foreignKeyID into j3
from t3 in j3.DefaultIfEmpty()
select new { t1, t2, t3 };
You dont need that terrible join syntax if you FK's are properly setup.
You would probably write:
var q = from t1 in dc.table1s
from t2 in t1.table2s.DefaultIfEmpty()
from t3 in t1.table3s.DefaultIfEmpty()
select new { t1, t2, t3 };