LinqToSql: Select field from list used within a query - c#

I perform a query on a table Installation to get a list of Ids that are needed to query a table Product on a different database (before you ask, it has to be this way, can't query across dbs). Here's what the list looks like:
class Installation
{
Guid InstallationId
Guid ProductId
}
List<Installation> installs;
I don't have any problems using this list for the query in to the Product table which looks like this:
var prods = (from p in context.Product
where installs.Select(i => i.ProductId).Contains(p.ProductId)
select new
{
ProductNumber = p.ProductNumber
// How do I get InstallationId from installs??
}).ToList();
What I need to know is how I can retrieve InstallationId from the list and store it in the new list?
Thanks in advance.

You should do a join
var products = (from product in context.Product
join install in installs
on install.ProductId equals product.ProductId
select new {
ProductNumber = product.ProductNumber
InstallationId = install.InstallationId
}
).ToList();

A slight refactoring of Jason's answer to allow for the LinqToSql exception.
var products = (from product in context.Product
where installs.Select(i => i.ProductId).Contains(p.ProductId)
select product).ToList()
var installedProducts = (from product in products
join install in installs
on install.ProductId equals product.ProductId
select new
{
ProductNumber = product.ProductNumber,
InstallationId = install.InstallationId
}).ToList();

Related

Too much data in Contains (Linq): How to increase performace

I have a linq query like this:
from a in context.table_A
join b in
(from temp in context.table_B
where idlist.Contains(temp.id)
select temp)
on a.seq_id equals b.seq_id into c
where
idlist.Contains(a.id)
select new MyObject
{
...
}).ToList();
idlist is List
The problem I have is that the idlist has too many values (hundreds of thousands to several million records). It works fine with few records but when there are too many records, the contains function is error.
Error log is
The query plan cannot be created due to lack of internal resources of
the query processor. This is a rare event and only occurs for very
complex queries or queries that reference a very large number of
tables or partitions. Make the query easy.
I want to improve the performance of this section. Any ideas?
I would suggest to install extension linq2db.EntityFrameworkCore and use temporary tables with fast BulkCopy
public class IdItem
{
public int Id { get; set; }
}
...
var items = idList.Select(id => new IdItem { Id = id });
using var db = context.CreateLinqToDBConnection();
using var temp = db.CreateTempTable("#IdList", items);
var query =
from a in context.table_A
join id1 in temp on a.Id equals id1.Id
join b in context.table_B on a.seq_id equals b.seq_id
join id2 in temp on b.Id equals id2.Id
select new MyObject
{
...
};
// switch to alternative translator
var query = query.ToLinqToDB();
var result = query.ToList();

linq query using joins and aggregate functions

I want to write a linq query which retrieves the data in the following format.
Assume that there are two tables - Department and Employee
Department
Dept_id| Manager_id
Employee
Emp_id| Dept_id| Emp_data
The relationship between Department and Employee table is one to many. The Department table also stores the manager employee id in that particular department. So Manager_id is nothing but the employee_id.
Now I want to get the data as follows
Dept_id, Manager_id, Emp_data(data of Manager_id), Count(employees in that department)
If I do the join on two tables i can get data of Manager but unable to get the count of all employees in that department. Any help would be appreciated.
You could do something like this:
var result=
(
from dep in db.Department
join emp in db.Employee
on dep.Manager_id equals emp.Emp_id
select new
{
dep.Dept_id,
emp,
NumberOfEmp= db.Employee.Count(c=>c.Dept_id==dep.Dept_id)
}
).ToList();
Where db is the linq data context
You could do a group join. If you have a preferred handcoded SQL statement that you would like to be generated from your LINQ query. You may want to experiment a bit with different formats to see which one allows you to generate the "best" SQL.
var result = from d in context.Departments
join e in context.Employees on d.dept_id equals e.dept_id into g
select new {
dept_id = d.dept_id,
manager_id = d.manager_id,
manager_data = g.Single(x => x.emp_id == d.manager_id).emp_data,
employee_count = g.Count()
};
or
var result = from d in context.Departments
join e in context.Employees on d.dept_id equals e.dept_id into g
from m in g where m.emp_id == d.manager_id
select new {
dept_id = d.dept_id,
manager_id = d.manager_id,
manager_data = m.emp_data,
employee_count = g.Count()
};

Why does my linq to sql query fail?

I am new to .Net (and stackoverflow) so I am running into a few problems. One vexing problem is this linq query below. Some information about the code. CustomerCart is a separate Model class in my project where the products member is a list of products. If I remove the products from the select new CustomerCart portion it runs fine and the data is present. So I figure it is my syntax. Can I not put a linq statement inside an assignment constructor? Any help would be appreciative. Thank you in advance.
var k = from s in store.Customers
join p in store.ShoppingCarts on s.custId equals p.customerId
select new CustomerCart()
{
FirstName = s.firstName,
LastName = s.lastName,
products = (from j in store.Products
where p.productId == j.productId
select j).ToList(),
CartID = p.cartId,
CustomerID = s.custId,
};
**Edit
Error I receive: The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery`1[productShop.Models.CustomerCart]', but this dictionary requires a model item of type 'productShop.Models.CustomerCart'.
Sorry for not placing the error message with my question.
Try this query instead:
var k =
from s in store.Customers
join p in store.ShoppingCarts on s.custId equals p.customerId
join j in store.Products on p.productId equals j.productId into products
select new CustomerCart()
{
FirstName = s.firstName,
LastName = s.lastName,
products,
CartID = p.cartId,
CustomerID = s.custId,
};

How do I write Joins between multiple tables with Linq and ASP.Net Forms

I've implemented a solution that works, but LINQ is a something nre for me and I am struggling to find the required information.
Here is what I have:
var prodCat = from pc in db.ProductCategories
where pc.Category == Int32.Parse(CategoriesDropper.SelectedValue)
select pc;
List<int> productIds = new List<int>();
foreach (var pc in prodCat)
{
productIds.Add(pc.Product);
}
var products = from p in db.Products
where productIds.Contains(p.Id)
select p;
ProductsGridView.DataSource = products;
ProductsGridView.DataBind();
Ideally I would like to achieve the same result with a single select rather than two.
var products = from pc in db.ProductCategories
join p in db.Products on pc.Product equals p.Id
where pc.Category == Int32.Parse(CategoriesDropper.SelectedValue)
select p;
ProductsGridView.DataSource = products;
ProductsGridView.DataBind();
See LINQ - Join Operators in C# for Visual Studio 2010 for reference.
Hope this helps!
You don't mention which flavor of LINQ you are using, but assuming you have the associations set between ProductCategories and Products, you should be able to do something like this:
int Cat = Int32.Parse(CategoriesDropper.SelectedValue);
var products = from pc in db.ProductCategories
where pc.Category == cat
from p in pc.Products
select p;
var selectedCategory = Int32.Parse(CategoriesDropper.SelectedValue); //Parse the value once
var products =
from p in db.Products //foreach product in the database
join pc in db.ProductCategories
on pc.Product equals p.Id //where the Ids match
where pc.Category == selectedCategory //and with the same category
select p; //select the product
ProductsGridView.DataSource = products;
ProductsGridView.DataBind();

LINQ to SQL return statement

In a project i have a LINQ to SQL class which is OrderingSystem.dbml. I have the following code and in the select statement i want to retrieve only some of the rows from each table(Products - Categories). But of course the return statement that i have right now it is not correct. What is the correct return statement to use?? Thanks in advance
OrderingSystemDataContext database = new OrderingSystemDataContext();
public List<Product> GetProductsByCategoryID(int CategoryID)
{
var result = from p in database.Products
join c in database.Categories
on p.CategoryID equals c.CategoryID
where p.CategoryID == CategoryID
select new { p.ProductName, p.ProductPrice, p.ProductDescription, c.CategoryName };
//This is not working
return result.ToList();
}
On the select new you have to specify the type if you then want to retrieve a list of products, right now it creates an anonymous type. Try changing with :
OrderingSystemDataContext database = new OrderingSystemDataContext();
public List<Product> GetProductsByCategoryID(int CategoryID)
{
var result = from p in database.Products
join c in database.Categories
on p.CategoryID equals c.CategoryID
where p.CategoryID == CategoryID
//Assuming that these are the names of your properties
select new Product(){ProductName = p.ProductName, ProductPrice = p.ProductPrice, ProductDescription = p.ProductDescription, CategoryName = c.CategoryName };
return result.ToList();
}
It is because in the LINQ expression, you did a select new { } which creates an anonymous object, while your method returns a List of Product. You should change the select statement so it becomes select new Product() { ProductName = p.ProductName, ... the rest depends on the structure of your Product class.
By using the "select new" LINQ operation, you are creating an anonymous type. You can access the properties of that anonymous type within the current scope of the objects' creation, but you cannot return that anonymous type using any kind of recognizable type. You have two options:
Create a new class (e.g. Product) and create instances of that type as part of your select statement (as the other answers instruct)
Return the collection as List<object>. If you do this, you can still retrieve values from the objects, but you will need to do so via reflection. This can be quite valid if you are using the collection as the data source in a data binding scenario.
Your return type is Product but your query result uses an anonymous type.
Change this line:
select new { p.ProductName, p.ProductPrice, p.ProductDescription, c.CategoryName };
to something like this:
select new Product { Name = p.ProductName, Price = p.ProductPrice, Description = p.ProductDescription, Category = c.CategoryName };
EDIT:
Try just replacing it with:
select p;

Categories

Resources