Linq how to use a subSelect as a virtual table in FROM - c#

There may be similar questions out here but none that I could find for doing a subSelect in the FROM clause as a virtual table.
Most of the columns I need are in one table. There are a few columns needed from different tables that I cannot join on without getting a Cartesian join.
Here is my SQL query:
SELECT meter_name, a.loc_id, a.loc_name, a.facility_name, meter_type
FROM meter_table, (SELECT loc_id, loc_name, facility_name
FROM facility_table
WHERE id = 101) a
WHERE meter_id = a.fac_id
I have no idea how to convert this into Linq and it must be done tonight for a demo in the morning.

Assume this represents your meter_table within your database
in this case each element of the list represents a record in the database table holding the appropriate attributes
i.e the table columns will become the properties of each object
List<Meter> meter_table = new List<Meter>();
Assume this represents the facility_table table you want to join with.
same goes here, each element of the list represents a record in the database table holding the appropriate attributes
i.e the table columns will become the properties of each object
List<Facility> facility_table = new List<Facility>();
then perform the inner join like so:
var query = from m in meter_table
join a in facility_table on m.meter_id equals a.fac_id
where a.id == 101
select new { meter_name = m.MeterName,
loc_id = a.LocId,
facility_name = a.FacilityName,
meter_type = m.MeterType
};
where m.MeterName, a.LocId, a.FacilityName, m.MeterType are properties of their respective types.
it's also worth noting the variable query references an IEnumerable of anonymous types. However, if you want to return an IEnumerable of strongly typed objects then feel free to define your own type with the appropriate properties then just change select new to:
select new typeName { /* assign values appropriately */}
of the above query.

Related

Linq to Sql - Manual association with manual parameter

I have the following tables in my database:
SageAccount
ID (bigint)
LegacyID (nvarchar)
Customer (bit)
Consignments
ID (bigint)
Customer (nvarchar)
What I want to do is have a navigation property/association in my Linq to Sql dbml from Consignment to SageAccount. The difficulty with this is that not only do we need to match SageAccount.LegacyID => Consignments.Customer but we also need to only join to sage accounts where SageAccount.Customer is TRUE. So on the Consignments end, it isn't joining onto a field but instead a static value.
Is this possible in Linq to Sql? Note this database doesn't (and unfortunately can't) have any foreign keys setup in the database.
Yes it is possible. linq have join method. You can use it ike this in your situation:
var res = from sageAccount in _context.SageAccount
join consignments in _context.Consignments
on
new
{
LegacyID = sageAccount.LegacyID,
Customer = sageAccount.Customer
}
equals
new
{
LegacyID = consignments.ID,
Customer = true
}
select new { SageAccountID = sageAccount.ID };
Note that Property name, Type and order in the anonymous objects that you're joining on must match.
You can't use OR and AND in joins - use just equals one object to other.
This will have a this kind of result in your SQL:
SELECT [t0].[ID] AS [SageAccountID]
FROM [dbo].[SageAccount] AS [t0]
INNER JOIN [dbo].[Consignments] AS [t1] ON (([t0].[LegacyID]) = [t1].[ID])
AND ([t0].[Customer] = 1)

What is the type of this inner join LINQ query?

I annoys me very much when programmers use var instead being precise and write the correct type. In Microsoft tutorial: http://msdn.microsoft.com/en-us/library/bb397927.aspx
I have found this explanation of inner join(below). What is probably the type of innerJoinQuery because it looks like mash up of 2 strings but we don't know what is the result type.
Quote:
Join operations create associations between sequences that are not explicitly modeled in the data sources. For example you can perform a join to find all the customers and distributors who have the same location. In LINQ the join clause always works against object collections instead of database tables directly.
C#
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
In LINQ you do not have to use join as often as you do in SQL because foreign keys in LINQ are represented in the object model as properties that hold a collection of items. For example, a Customer object contains a collection of Order objects. Rather than performing a join, you access the orders by using dot notation:
EDIT: Let's rephrase this question. What else I can put instead of var here?
The result of this linq query is a sequence of objects of an anonymous type with two properties. One of them is called CustomerName and the other is called DistributorName. Both of them are quite possible of type string.
In order you avoid the var, you have to declare a class with these two properties, like below:
class ClassName
{
public string CustomerName { get; set; }
public string DistributorName { get; set; }
}
Then you have to change you linq query to the following one:
IEnumerable<ClassName> innerJoinQuery = from cust in customers
join dist in distributors
on cust.City equals dist.City
select new ClassName
{
CustomerName = cust.Name,
DistributorName = dist.Name
};
However I don't see any benefit in the above approach if you jsut want to get the results of this query and iterate through them or something else. In other words, I think that var is used correctly here. I mean it doesn't createa any ambiguities of what you do.

How to create a type of list from joined entities (tables)?

I am new to entity framework. Here is my simple problem.
I have a SQL database mapped automatically to ADO .NET Entity Data Mode, I wrote a function
public List<table1> GetTable1()
{
return ( from t in context.table1 select t).ToList();
}
and then I attach the data:
List<table> list1 = GetTable1();
GridView1.DataSource = list1;
but when I wanted to use joined table1 and table2 in select statement I don't know what type of List to use.
What type should the function return so I could attach it to my GridView?
My only solution now is to create view on database joining those 2 tables and then update the entity Model, but this might be not very elegant way.
Thanks for help :)
This is quite similar to this question: How to get 2 different values in 2 different tables using c# linq
You need to create a new class that can encapsulate the result you want back. That way, you can return the type from your data access layer.
Use Anonimous Type inside the method where datasource is bound :
var list1 = (from t in context.table1 select new { ColumnFromTable1 = "whatever", FromOtherTable = "other" }).ToList();
GridView1.DataSource = list1;
Of course, you need to know how to join tables, the key point here is:
new { ColumnFromTable1 = "whatever", FromOtherTable = "other" }

Combine two or more table into one object

I need to combine two or more table into one object by using C# 4,0... I wrote a class for a table which included simple select selectbyid insert update and update.... it works fine for single table... by the way I have two attribute which specifies table name column name and primarykey... by using all these I can create my simple methods but I need to select and update more table in one object or method... what should I do or what would you suggest about it...
Example:
users and customer table I have foreign keys which defined...
If you`re using linq to sql, you can join the other tables like
var q =
from s in db.Suppliers
join c in db.Customers on s.City equals c.City
select new {
Supplier = s.CompanyName,
Customer = c.CompanyName,
City = c.City
};
as just copy & paste from a sample of MSDN LINQ to SQL: .NET Language-Integrated Query for Relational Data

Linq to Sql - Populate JOIN result into a List

I am not sure if this can be done, but here's the scenario.
I want to turn this sql into linq:
SELECT * FROM Department d
INNER JOIN Employee e ON e.DepartmentID = d.DepartmentID
Department - Employee is 1 to many relationship.
I have created a custom object that I would like to populate the result into.
public class DepartmentSummary
{
public Department Department { get; set; }
public List<Employee> Employees {get; set;}
}
The Linq I came up with is
var result = from d in dba.Department
join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1
select new DepartmentSummary
{
Department = d,
Employees = j1.ToList()
};
I tried it out and it's not working. Can anyone shed some light for me please? I would like to perform an inner join between Department and Employee. For each Department in the resultset, I would like to create one DepartmentSummary object which holds that department and a list of employees belonging to that department.
Does Linq provides an ad hoc solution for this or must I iterates through the result set and create a list of DepartmentSummary manually?
Thanks,
EDIT:
Looks like this works for me
var result = from d in dba.Department
join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1
where j1.Count() > 0
select new DepartmentSummary
{
Department = d,
Employees = j1.ToList()
};
The thing is that you're not really taking one SQL and trying to create a Linq-query out of it.
If you were, you'd notice that your SQL query does not really produce one row per department, but it will repeat the department information for each employee in that department.
Now, an initial naive look would suggest you use a group-by clause, since that would allow you to split the data into individual groupings for each department, but groupings in SQL does not really give you a key+all-matching-rows type of result, rather it allows you to do aggregate calculations, like "for each department, how many employees do I have".
So, in order to do what you want, you need to basically do a normal join, which will give you each employee, coupled with the appropriate department information (ie. each employee will be linked to his/her department), and then you need to construct the rest of the data structure yourself.
Now, having said that, if you have the proper relationships set in your data context related classes, each department should already have some kind of property that contains all employees in that department, so perhaps the simple query is just "give me all departments", and then you can, for each department, retrieve the employees?
Of course, doing that would likely execute one SQL for each department, but in this case, you're back to "give me all employees with their department information" and you have to build code to handle the rest.
LINQ to SQL doesn't understand your ToList() call, but you might be able to select the sequence of joined elements and then use LINQ to Objects (via AsEnumerable()) to map to your DepartmentSummary object:
var qResult = from d in dba.Department
join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1
select new
{
Department = d,
Employees = j1
};
var result = from d in qResult.AsEnumerable()
select new DepartmentSummary()
{
Department = d.Department,
Employees = e.Employees.ToList()
};
Sounds like you're looking to get around lazy loading?
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Department>(d => d.Employees);
using (var dba = new MyDataContext())
{
dba.LoadOptions = dlo;
var result = from d in dba.Department
select d;
}
Now, if you don't have a relationship defined between Department and Employees (the Linq2Sql designer will do this for you if you have database relationships setup) then you should look into doing that. It makes it all dramatically easier. In fact, you don't even need your campaign summary.
This problem is due to the nature of the query. When you join Department to Employee, you'll get back one record for every Employee. This means that your ToList() statement is expecting multiple employees per department, but due to the join, always getting one.
Change your query to
var result =
from d in dba.Department
select new tCampaignSummary
{
Department = d,
Employees = dba.Employee.Where(e => e.DepartmentID ==
d.DepartmentID).ToList()
};
I've tested this and it works.
What it does differently is selects only one record per Department (not per employee) then it gets the zero to many corresponding employees for each dept and converts them to a list.
Good luck!
EDIT
As requested, here is the generated SQL:
SELECT [t0].*, [t1].*
(
SELECT COUNT(*)
FROM [dbo].[Employee] AS [t2]
WHERE [t2].[DepartmentID] = [t0].[DepartmentID]
) AS [value]
FROM [dbo].[Department] AS [t0]
LEFT OUTER JOIN [dbo].[Employee] AS [t1]
ON [t1].[DepartmentID] = [t0].[DepartmentID]
ORDER BY [t0].[DepartmentID], [t1].[IndexID]
The only modification is that LINQ will not do [t0].*, instead it will enumerate each field. Since I had to guess at the fields, I left them out to make the SQL clearer.

Categories