LINQ join multiple tables on same column - linq

I have a table names TestNotifications which has a CompanyID and a TestCompanyID. Those IDs link to a Companies table which has a companyName column. I need to get the companyName for the company and testCompany. The code below isn't working, I'm getting a cannot implicitly convert error. Any help appreciated.
testNotifications = from t in db.CT_TestNotifications
join c in db.CT_Companies on t.CompanyID equals c.CompanyID
join tc in db.CT_Companies on t.TestCompanyID equals tc.CompanyID
select new
{
t.TestNotificationID,
c.CompanyName,
//tc.CompanyName
TestCompanyName = tc.CompanyName
};
Here is the error:
Cannot implicitly convert type 'System.Linq.IQueryable<AnonymousType#1>' to
'System.Linq.IQueryable<CT_TestNotification>'. An explicit conversion exists
(are you missing a cast?)

You're projecting into an anonymous type but testNotifications expects CT_TestNotification.
Try creating an instance of CT_TestNotification in your select:
testNotifications = from t in db.CT_TestNotifications
join c in db.CT_Companies on t.CompanyID equals c.CompanyID
join tc in db.CT_Companies on t.TestCompanyID equals tc.CompanyID
select new CT_TestNotification // Here's the major difference
{
PropName = t.TestNotificationID, // PropName must be changed to the
PropName = c.CompanyName, // properties of your actual class
//tc.CompanyName
TestCompanyName = tc.CompanyName
};

See if your join on criteria are of the same types - IE is t.CompanyID an int and c.CompanyID.

I suspect the issue lies in how you declared testNotifications. If you did something like the following, you would see that error:
IQueryable<CT_TestNotifications> testNotifications;
testNotifications = from t in db.CT_TestNotifications
join c in db.CT_Companies on t.CompanyID equals c.CompanyID
join tc in db.CT_Companies on t.TestCompanyID equals tc.CompanyID
select new
{
t.TestNotificationID,
c.CompanyName,
//tc.CompanyName
TestCompanyName = tc.CompanyName
};
You would also get this same issue if you declared the testNotifications at the start and then continued with the query later on because you are trying to change the type of the value from the known type to an anonymous type.:
var testNotifications = db.CT_TestNotifications;
testNotifications = from t in testNotifications
join c in db.CT_Companies on t.CompanyID equals c.CompanyID
join tc in db.CT_Companies on t.TestCompanyID equals tc.CompanyID
select new
{
t.TestNotificationID,
c.CompanyName,
//tc.CompanyName
TestCompanyName = tc.CompanyName
};
Since you are projecting an anonymous type, you need to use type inference and not explicitly declare the variable:
var testNotifications = from .. select ..;

Related

CRM 2011- LINQ query joining Account, Case and Activity entity

I try to make the following query using Account, Case and Activity entities :
*var findCases =
from a in context.AccountSet
join c in context.IncidentSet
on a.AccountId equals c.CustomerId.Id
join p in context.ActivityPointerSet
on c.Id equals p.RegardingObjectId.Id
select new
{
TicketNumber = c.TicketNumber,
IncidentId = c.IncidentId,
CreatedOn = c.CreatedOn,
StateCode = c.StateCode,
AccountName = a.Name
};*
The execution of this query gives the error:
AttributeFrom and AttributeTo must be either both specified or both ommited. You can not pass only one or the other. AttributeFrom: , AttributeTo: regardingobjectid
Any suggestion will be appreciated.
Regards.
Radu Antonache
Remove CasesForAccount from the query..
*var findCases =
from a in context.AccountSet
join c in context.IncidentSet
on a.AccountId equals c.CustomerId.Id
join p in context.ActivityPointerSet
on c.Id equals p.RegardingObjectId.Id
select new
{
TicketNumber = c.TicketNumber,
IncidentId = c.IncidentId,
CreatedOn = c.CreatedOn,
StateCode = c.StateCode,
AccountName = a.Name
};*

Linq to entities outer join, then an inner join

i have this code:
var query = (from p in dc.GetTable<Person>()
join pa in dc.GetTable<PersonAddress>() on p.Id equals pa.PersonId into tempAddresses
from addresses in tempAddresses.DefaultIfEmpty()
select new { p.FirstName, p.LastName, addresses.State });
this works good, as a outer join for persons with their (optional) address.
Now i want to join addresstype to this query with an inner join, because every address has exactly one addresstype.
So for every person, get the address, and if it has an address, also get the addresstype.
So i created this (added the inner join to addresstype):
var query = (from p in dc.GetTable<Person>()
join pa in dc.GetTable<PersonAddress>() on p.Id equals pa.PersonId into tempAddresses
from addresses in tempAddresses.DefaultIfEmpty()
join at in dc.GetTable<AddressTypes>() on pa.addresstypeid equals at.addresstypeid
select new { p.FirstName, p.LastName, addresses.State, at.addresstype });
Now i get an null reference error on the pa.addresstypeid when the person has no address....
Is there a way to create this in linq?
The above code is behavioural exactly like my code, but my code has different entities but i'm not allowed to show actual code...
EDIT:
here is an example from my code which actually works: (replace the tables with foo/bar)
from foo in foos
join bar in new barRepository(SessionTicket).GetList()
on foo.barId equals bar.barId
join barpersonbar in new barPersonbarRepository(SessionTicket,personId).GetList().Where(z=>z.PersonId == personid)
on bar.barId equals barpersonbar.barId
into outerbarpersonbar
from barpersonbar in outerbarpersonbar.DefaultIfEmpty()
Isn't that the same as in your comment, that 'pa' is out of scope, isn't that the 'bar' in this code
pa isnt in scope once you use the into
change
on pa.addresstypeid equals
to
on addresses.addresstypeid equals

Why is LINQ-to-Entities is generating an extra left outer join

Background
I have 2 tables: OrderItem and OrderItemValue. An OrderItem can have 0 or 1 OrderItemPackageValue. The Primary key in both tables is the same and there is a foreign key reference from OrderItems to OrderItemPackageValue
LINQ
var dummy =
from orderItem in context.OrderItems
select new
{
OrderID = orderItem.OrderID,
LineNumber = orderItem.LineNumber,
PackageValue = (decimal?)orderItem.OrderItemPackageValue.PackageValue
};
var dummy2 = dummy.ToArray();
SQL
SELECT
[Extent1].[OrderID] AS [OrderID],
[Extent1].[LineNumber] AS [LineNumber],
[Extent3].[PackageValue] AS [PackageValue]
FROM [dbo].[OrderItems] AS [Extent1]
LEFT OUTER JOIN [dbo].[OrderItemPackageValues] AS [Extent2] ON ([Extent1].[OrderID] = [Extent2].[OrderID]) AND ([Extent1].[LineNumber] = [Extent2].[LineNumber])
LEFT OUTER JOIN [dbo].[OrderItemPackageValues] AS [Extent3] ON ([Extent2].[OrderID] = [Extent3].[OrderID]) AND ([Extent2].[LineNumber] = [Extent3].[LineNumber])
I'm trying to get this via Linq2Entities (MSSQL) and it seems to be generating an extra outer join, and I can't figure out how to get rid of it.
This is a bug; see here and here.
Workaround: Try changing your relationship from 1 : Many to 0..1 : Many

Group by, Sum, Join in Linq

I have this simple sql query:
select c.LastName, Sum(b.Debit)- Sum(b.Credit) as OpenBalance from Balance as b
inner join Job as j on (b.Job = j.ID)
inner join Client as c on (j.Client = c.ID)
Group By c.LastName
and I am trying to convert it to work in linq like this:
from b in Balance
join j in Job on b.Job equals j.ID
join c in Client on j.Client equals c.ID
group b by new { c.LastName } into g
select new {
Name = c.Lastname,
OpenBalance = g.Sum(t1 => t1.Credit)
}
but when I try to run it in LINQPad I get the following message:
The name 'c' does not exist in the
current context
and it highlights c.Lastname in select new statement.
Any help on this will be greatly appreciated.
Thank you.
Well, you've grouped b by c.LastName. So after the grouping operation, you're dealing with g which is a grouping with the element type being the type of b, and the key type being the type of c.LastName. It could well be that all you need is:
select new {
Name = g.Key,
OpenBalance = g.Sum(t1 => t1.Credit)
}
... but if you need to get at any other aspects of c, you'll need to change your grouping expression.

linq nested query

I have a query that has the following
var myvar = from table in MyDataModel
where.....
select new MyModel
{
modelvar1 = ...,
modelvar2 = (from..... into anothervar)
}
What I want to do is have modelvar2 be a join between the result I currently get from anothervar with another table in MyDataModel.
Thanks
The parenthesis looks more like a subquery than a join. This is how you do a join.
Example tables from the AdventureWorks database.
using (DataClasses1DataContext context = new DataClasses1DataContext())
{
// If you have foreign keys correctly in your database you can
// join implicitly with the "dot" notation.
var myvar = from prod in context.Products
where prod.ListPrice < 10
select new
{
Name = prod.Name,
Category = prod.ProductSubcategory.ProductCategory.Name,
};
// If you don't have foreign keys you need to express the join
// explicitly like this
var myvar2 = from prod in context.Products
join prodSubCategory in context.ProductSubcategories
on prod.ProductSubcategoryID equals prodSubCategory.ProductSubcategoryID
join prodCategory in context.ProductCategories
on prodSubCategory.ProductCategoryID equals prodCategory.ProductCategoryID
where prod.ListPrice < 10
select new
{
Name = prod.Name,
Category = prodCategory.Name,
};
// If you REALLY want to do a subquery, this is how to do that
var myvar3 = from prod in context.Products
where prod.ListPrice < 10
select new
{
Name = prod.Name,
Category = (from prodSubCategory in context.ProductSubcategories
join prodCategory in context.ProductCategories
on prodSubCategory.ProductCategoryID equals prodCategory.ProductCategoryID
select prodCategory.Name).First(),
};
// If you want to get a list from the subquery you can do like this
var myvar4 = from prodCategory in context.ProductCategories
select new
{
Name = prodCategory.Name,
Subcategoreis = (from prodSubCategory in context.ProductSubcategories
where prodSubCategory.ProductCategoryID == prodCategory.ProductCategoryID
select new { prodSubCategory.ProductSubcategoryID, prodSubCategory.Name }).ToList(),
};
}
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[ShipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPostalCode], [t0].[ShipCountry]
FROM [Orders] AS [t0]
INNER JOIN ([Order Details] AS [t1]
INNER JOIN [Products] AS [t2] ON [t1].[ProductID] = [t2].[ProductID]) ON [t0].[OrderID] = [t1].[OrderID]
can be write as
from o in Orders
join od in (
from od in OrderDetails join p in Products on od.ProductID equals p.ProductID select od)
on o.OrderID equals od.OrderID
select o

Resources