linq to sql using foreign keys returning iqueryable(of myEntity] - linq

I'm trying to use Linq to SQL to return an IQueryable(of Project) when using foreign key relationships. Using the below schema, I want to be able to pass in a UserId and get all the projects created for the company the user is associated with.
DB tables:
Projects
Projid
ProjCreator FK (UserId from UserInfo table)
Companyid FK (CompanyID from Companies table)
UserInfo
UserID PK
Companyid FK
Companies
CompanyId PK
Description
I can get the iqueryable(of project) when simply getting the ProjectCreator with this:
Return (From p In db.Projects _
Where p.ProjectCreator = Me.UserId)
But I'm having trouble getting the syntax to get a iqueryable(of projects) when using foreign keys. Below gives me an IQueryable(of anonymous) but I can't seem to convince it to give me an IQueryable(of project) even if I try to cast it:
Dim retval = (From p In db.Projects _
Join c In db.Companies On p.CompanyId Equals c.CompanyId _
Join u In db.UserInfos On u.CompanyId Equals c.CompanyId _
Where u.Login = UserId)

Simply select the project:
Dim retval = (From p In db.Projects _
Join c In db.Companies On p.CompanyId Equals c.CompanyId _
Join u In db.UserInfos On u.CompanyId Equals c.CompanyId _
Where u.Login = UserId _
Select p)

Related

EF linq query working in linqpad but not in the App

I have creatred a query in linqpad and it works but when i try to use it in my blazor app the app throws an error.
I have three tables, tblOpportunity, tblOppStatus and lkpStatus
and an opportunity can have many status's depending on how mature the enquiry is. So i need to get all the latestest status for each opportunity. I also want to be able to filter the dataset so i get only opportunities with staus of x, y and z
void Main()
{
var output=from o in TblOpportunities
join sub in (
//get the latest status ID for the from the joining table
from smax in TblOppStatuses
group smax by smax.OpportunityID
into g
select new
{
OName = g.Key,
MaxS = (from t2 in g select t2.OppStatusID).Max()
})
on o.OpportunityID equals sub.OName
join st in TblOppStatuses on sub.MaxS equals st.OppStatusID
//get the statu sname form the lookup table
join lst in Lkp_Statuses on st.StatusID equals lst.StatusID
join c in TblClients on o.ClientID equals c.ClientID
select new
{
c.ClientName,
o.OpportunityName,
sub.MaxS,
lst.Status,
lst.StatusID
};
int[] filter = { -1, 62};
output.Where(of=>filter.Contains(of.StatusID))
.Dump();
}
The error that comes in the subquery
MaxS = (from t2 in g select t2.OppStatusID).Max()
if i comment this out the query runs but doesn't give me what i want. Can anyone advise what i am doing wrong As I say it works fine in Linqpad.

LINQ Weirdness with joining tables

I have to join multiple tables. The tables have similar data for each table.
ID
(table id for FK)
Name
Description
Owner
from d in Departments
join f in Functions on d.DepartmentID equals f.DepartmentID
join pg in Processes on f.FunctionID equals pg.FunctionID
select new { d.DepartmentID, f.Name, pg.Name }
This throws an error 'An anonymous type cannot have multiple properties with the same name'
is there a better way to join these tables?
Should I do Select new { d, f, pg } ? Is it easy to grab the data from that?
I am very new to LINQ so any help is appreciated.
The compiler creates the properties of the anonymous type based on the property you use. In your case you use the property Name twice. Once in f.Name and once in pg.Name.
To fix it you have to specify at least one of the two property names explicitly:
select new { d.DepartmentID, FunctionName = f.Name, ProcessName = pg.Name }
You just need to give unique names for the two Name properties. Something like:
from d in Departments
join f in Functions on d.DepartmentID equals f.DepartmentID
join pg in Processes on f.FunctionID equals pg.FunctionID
select new { d.DepartmentID, FName = f.Name, PGName = pg.Name }
When you don't specify your own names, the compiler will just use the full name of the property, but since in this case they are both just Name, it will generate an error.

LINQ join multiple tables on same column

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 ..;

Join statement in Linq to Sql

I need to write Join statment after writing query in linq
example :
var Query = (from Tab in Db.Employees
select Tab)
as i have some cases to perform join operation so
i need to do it on this Query Query.Join(Join with another Table like Department); I need the Syntax
if (DeptID != -1){ Query.Join(Join with table Department where FkDeptID = DeptID); }
Consider the usage of join in the LINQ 'query syntax':
from t1 in db.Table1
join t2 in db.Table2 on t1.field equals t2.field
select new { t1.field2, t2.field3}
Something like this?
var results = (from q in Query
join m in myList on q.SomeID = m.SomeID
select unknown);
Try using this query:
var Query =
from e in Db.Employees
join d in Db.Departments on e.FkDeptID equals d.DeptID into departments
select new
{
Employee = e,
Department = departments.SingleOrDefault(),
};
This works assuming that when e.FkDeptID == -1 that there is no record in the Departments table and in that case Department would be assigned null.
You should never have more than one department for an employee so I've used SingleOrDefault rather than FirstOrDefault.

linq where clause not in select statement

Can someone help me to convert from SQL Query to LINQ VB.NET:
select rls.* from Roles rls(nolock)
where rls.id not in (
select r.ID from usersRole ur (nolock)
inner join Roles r(nolock) on ur.RoleID = r.ID
where user_id = 'NY1772')
Thanks
i find my own answer...
'construct a where ID list
Dim lstRoleIDs = From ur In ctx.UsersRoles _
Join rl In ctx.Roles _
On ur.RoleID Equals rl.ID _
Where ur.User_ID = UserId _
Select rl.ID
Dim newQ = (From r In ctx.Roles _
Where Not lstRoleIDs.Contains( _
r.ID) _
Select New UserRoleList With {.ID = r.ID, .PermDesc = r.ID & " - " & r.Permission & " - " & r.PermissionDescription})
If you want to preserve the (NOLOCK) hints, I have blogged a handy solution using extension methods in C#. Note that this is the same as adding nolock hints to every table in the query.

Resources