Linq u getting slow - linq

i make a linq query matching two table primary key group by and mapped product only but getting slow
int mappedCount = (from product in products
from productMapping in DbContext.ProductCategoryMappings where product.TenantId.Equals(productMapping.TenantId.ToString())
&& product.ProductGuid.ToUpper().Equals(productMapping.ProductId.ToString().ToUpper())
from tenantCustMapping in DbContext.TenantCustCategories
where tenantCustMapping.Id.Equals(productMapping.Value)
select 1).ToList().Sum();
Product mapped invoceindex as 1 and finaly sum of mapped count

Related

LINQ Equivalent of and SQL query with two inner joins and a left join

I would be grateful for help with a LINQ equivalent of the following SQL Query (which works). Below this SQL query I give some description of my simple data base and the problem I want to solve.
Select a.Name, a.OrderID,
b.ProductIDFirst, c1.productName ProductNameFirst,
b.ProductIDSecond , c2.productName ProductNameSecond
from Customers a
INNER JOIN ORDERS b ON a.OrderID = b.OrderID
left join products c1 on b.productidfirst = c1.productid
left join products c2 on b.ProductIDSecond = c2.productid
Background information on the database structure:
I have a simple SQL Server Database with three Tables named Products, Orders and Customers.
The business model is such that each order can have only two products (not more).
The Orders table has two foreign keys, though they both come from the Products table. These Foreign Key field Names in the Orders Table are ProductIDFirst and ProductIDSecond. These two Foreign Keys in the orders table correspond to two products that each order can have. Customers table has one Foreign Key which comes from the Orders Table.
Now I need help with an LINQ query that will return me all customers such that I get five fields - CustomerName, OrderID and Names of each of the two products that match the OrderID in the customer product.
Your links are non-existent, so here's a best attempt without seeing anything.
Assuming you have the following containers (you'll need to change them for your scenario):
var customers = new List<Customer>();
var orders = new List<Order>();
var products = new List<Product>();
You can do the following:
var query =
from a in customers
join b in orders
on a.OrderId equals b.OrderId
join c1 in products
on b.ProductIdFirst equals c1.ProductId into c1a
join c2 in products
on b.ProductIdSecond equals c2.ProductId into c2a
from p1 in c1a.DefaultIfEmpty()
from p2 in c2a.DefaultIfEmpty()
select new
{
Name = a.Name,
OrderId = a.OrderId,
ProductIdFirst = p1 == null ? null : p1.ProductIdFirst,
ProductNameFirst = p1 == null ? null : p1.ProductNameFirst,
ProductIdSecond = p2 == null ? null : p1.ProductIdSecond,
ProductNameSecond = p2 == null ? null : p1.ProductNameSecond,
};
In short, where you want a left join, project the join into something else (e.g. c1a, c2a) then call from on them using DefaultIfEmpty() which will set null when no matching item exists on the right-hand-side.

Using LINQ to get distinct items that do not join

I'm having problems running a LINQ query between two tables and returning an answer set that doesen't match.
TB_AvailableProducts
-Prod_ID
-Name
....
TB_Purchases
-Cust_ID
-Prod_ID
Is there a way to get all distinct products that a customer has not purchased by using 1 LINQ query, or do I have to be doing two separate queries, 1 for all products and 1 for purchased products, and compare the two?
This query will return all products, which do not have related record in purchases table.
int customerID = 1;
var query = from ap in context.TB_AvailableProducts
join p in context.TB_Purchases.Where(x => x.Cust_ID == customerID)
on ap.Prod_ID equals p.Prod_ID into g
where !g.Any()
select ap;
I don't think you need Distinct here if you don't have duplicated records in your products table.
Generated SQL query will look like:
SELECT ap.Prod_ID, ap.Name
FROM TB_AvailableProducts AS ap
WHERE NOT EXISTS (SELECT
1 AS C1
FROM TB_Purchases AS p
WHERE (1 = p.Cust_ID) AND (ap.Prod_ID = p.Prod_ID)
)

Linq query that results in one field in parent entity being a collection of child entities

I am trying to write a Linq query that results in a parent entity with one of the fields being a collection of entities of its related children. For example, I have a collection of all customers entities and a collection of all orders entities. The orders entities have a field called customerPK which contains the link to the related parent customer entity. I want to create a Linq query that joins the two collections and results in all the fields of the customer entity plus an additional field which is the collection object of all the related order entities for that specific customer entity.
Hopefully this should do the trick;
EDIT: Code updated to perform a Left Outer Join, based on this example; http://smehrozalam.wordpress.com/2009/06/10/c-left-outer-joins-with-linq/. This now includes Customers who have no orders.
var query = from c in customers
join o in orders on c.ID equals o.CustomerPK into joined
from j in joined.DefaultIfEmpty()
group j by c into g
select new { Customer = g.Key, Orders = g.Where(x => x != null) };
Note, the use of Where on the selection of the Orders grouping is so that null orders are filtered out at this point, instead of ending up with a grouping containing a single null Order for customers who don't have orders.
Then some example usage;
foreach (var result in query)
{
Console.WriteLine("{0} (ID={1})", result.Customer.Name, result.Customer.ID);
foreach (var order in result.Orders)
{
Console.WriteLine(order.Description);
}
}
This example results in an object with two fields, the Customer and then a group of related Orders, but there's no reason why you can't select the individual fields of your customer object in the query as you specified in your post.

Linq Sum for Multiple Joins

Can someone help me out with the following Linq statement? I'm trying to get join 4 tables through Linq, group by the last table and sum a property of the first.
var payments = (
from payment in db.Payments
join payees in db.cmsMembers on payment.PayeeID equals payees.nodeId
join payeeGroups in db.cmsMember2MemberGroups on payees.nodeId equals payeeGroups.Member
join groups in db.umbracoNodes on payeeGroups.MemberGroup equals groups.id
group groups by new {groups.text, payment} into groupedPayments
select new
{
Group = groupedPayments.Key.text,
Count = groupedPayments.Count(),
Amount = groupedPayments.Sum(?)
}
).ToList();
The issue I'm having is that the in the groupedPayments.Sum(..) call I'm only getting access to the "groups" object. This is fine for the Group name and count aspect but the SUM has to be performed on the payment.Amount property.
I've managed to resolve my issue. I hadn't realised that the object in the group declaration would become the actual object witin the resulting group item. By altering the original statement to the following:
group payment by groups into groupedPayments
it seems that each instance of groupedPayments.Key in the select statement now corresponds to the payment row which is what I required.

Linq to SQL: order by value in related table

I have 2 tables which in simplified form look like this:
Products(
id: int,
name: varchar
);
ProductSpecs(
product_id: int,
spec_name: varchar,
spec_value: int
);
Now I need to sort products (in linq to sql) by value of some specification item (eg. "price"). So I do something like this
var products = from p in db.Products
from ps in p.ProductsSpecs
where ps.spec_name == "price"
orderby ps.spec_value
select p;
The problem is that if there's no such ProductSpec with spec_name "price" the product is not included at all. I can add these products with Union or Concat but this way the sorting of the first part is not preserved.
What is the best way to deal with this?
Thanks.
First, I would recommend that you either do this in pure SQL as a function or Stored Procedure and then access this through linq, or add a price column to your product table. It seems like price would be a normal attribute to add to all of your products even if that price is NULL.
SQL:
select p.*
from products p
left outer join productspecs ps on
p.id = ps.product_id
and ps.spec_name = 'Price'
order by ps.spec_value
With that said, here's the weird bit of LINQ that should work on your table (I might have some of the column names spelled incorrectly):
var products = from p in db.Products
join ps in (from pss in db.ProductSpecs
where pss.spec_name== "Price"
select pss
) on p.id equals ps.product_id into temp
from t in temp.DefaultIfEmpty()
orderby t.spec_value
select p;
I tested this on some tables setup like above and created 5 products, three with prices in different value orders and this LINQ ordered them just like the SQL above and returned the null result rows as well.
Hope this works!
In ordinary SQL, you'd use an LEFT OUTER JOIN. This preserves rows that appear in the left-hand table (the one listed first), even when there's no matching row in the right-hand table (the second one listed, and the one that is outer joined). You end up with nulls for the values that should be, but weren't, present in the right-hand table. So, the price for those items missing a price would appear as NULL.
What that translates to in LINQ to SQL is another matter.
You might care to think about whether it is reasonable to have products that do not have a price. You're emulating something called EAV - Entity, Attribute, Value - tables, and they are generally regarded as 'not a good thing'.
Can you not just do a simple join?
var products =
from p in db.Products
join ps in db.ProductSpecs on p.id equals ps.product_id
where ps.spec_name == "price"
orderby ps.spec_value
select p;

Resources