Get Count from one value in three table linq2sql select? - c#

I just want the apartment complex count along with the other values. Only adding the count breaks the code. The error I get is "Sequence operators not supported for type 'System.String'." I have also tried changing apartCount to an int with no luck. Any help would be appreciated
using (var db = new DataClasses2DataContext())
{
var zips = (from s in db.ZipCodeServiceAvailabilities
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode
join a in db.pdx_apart_views on s.ZipCode equals a.Zip_Code
where (s.IsServiced == 1 && b.Ordering % 10 == 0)
orderby b.ZipCode
select new
{
zipCode = b.ZipCode.Trim(),
latitude = b.Latitude,
longitude = b.Longitude,
apartCount = a.Apartment_complex.Count()
}).ToArray();
}

I think you miss group by clause in your query.
or you can use corolated sub query in select clause. please explain your question more

Related

SQL Query to Linq to Entities - C#

I have been trying to convert this SQL statement into a linq as i am trying to move the functionality into a program.
Here is the SQL statement
SELECT cust.sg_group_name AS customer,
(SELECT Sum(du.used_space)
FROM sg_groups AS clnt
LEFT JOIN client_disk_usage AS du
ON clnt.sg_group_id = du.sg_group_id
AND clnt.group_role_id = 3
WHERE clnt.parent_group_id = cust.sg_group_id
AND du.day_of_month = 15
AND du.month_of_year = 05
AND du.used_space_year = 2016) AS disk_usage
FROM sg_groups AS cust
WHERE cust.group_role_id = 2
ORDER BY cust.sg_group_name
Essentially the output is just a list with two columns
customer disk_usage
Customer1 136401537652
Customer2 42208008210
If possible i just want to convert this to a linq statement. I have tried putting the query into LinqPad, but it doesn't seem to want to convert from SQL to Linq (just comes up with a blank white page). I have had a crack at the query myself, but i either get something that doesn't work altogether, or an incorrect number of results.
If anyone has any suggestions that would be great!
disk_usage(Sub Query) is a bit Complicated Part. Converted over here. Try this out
var CoreList = (from clnt in EntityName.sg_groups
join du in EntityName.client_disk_usage
on new { GrpId = clnt.sg_group_id, RoleId = clnt.group_role_id } equals new { GrpId = du.sg_group_id, RoleId = 3 } into LJ
from RT in LJ.DefaultIfEmpty()
where du.day_of_month == 15 && du.month_of_year == 05 && du.used_space_year == 2016
select new {clnt, du, RT}
).ToList();
var CoreListSet = CoreList.Select(i=> new YourEntityClass
{
//Fetch the ParentGroupId & UsedSpace
}).ToList();
var CoreListComplete = (from cl in CoreListSet
join cust in EntityName.sg_groups
on cust.sg_group_id equals cl.parent_group_id).ToList();
Now get the sum of CoreListComplete & just implement the base Select Query in Linq!
Apologies for the delayed response. I've marked #Anil answer up as this is the one that helped me find the answer. You solution did work #Sathish but it can be accomplished in a single command. Here is my final solution. Many thanks for your help!
storeGridUsage = (
from cust in db.sg_groups
from client in db.sg_groups
join du in db.client_disk_usage on client.SG_GROUP_ID equals du.SG_GROUP_ID
where client.GROUP_ROLE_ID == 3
where client.PARENT_GROUP_ID == cust.SG_GROUP_ID && du.DAY_OF_MONTH == day && du.MONTH_OF_YEAR == month && du.USED_SPACE_YEAR == year
where cust.GROUP_ROLE_ID == 2
orderby cust.SG_GROUP_NAME
group new {cust, du} by cust.SG_GROUP_NAME
into g
select new StoreGridUsage
{
CustomerName = g.Key,
DiskUsageInBytes = g.Sum(o => o.du.USED_SPACE)
}).ToList();

Convert shown query/subquery to group by?

Update: I have got a sql query working but am still having trouble converting it to linq2sql. Please see the code below..
I have a linq query that is pulling a lot of data but sometimes it times out due to the load it puts on the sql server. I am going to work on getting more efficient data (adding indexes etc) but I have also heard that using group by would be more efficient than using the sub query. Would a group by be more efficient and if so what would my query below look like with a group by? I am not familiar with group by yet. Please dont use lambda
Edit: New query which is still slow and can time out:
var query = (from s in db.ZipCodeServiceAvailabilities
join a in db.pdx_apart_views on s.ZipCode equals a.Zip_Code.Substring(0, 5) into a_join
from a in a_join.DefaultIfEmpty()
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode into b_join
from b in b_join.DefaultIfEmpty()
where
(s.IsServiced == 1 &&
b.Ordering % 10 == 0 &&
s.State == "AL")
group new { s, b, a } by new
{
s.ZipCode,
s.IsServiced,
b.Longitude,
b.Latitude,
b.Ordering
} into g
orderby
g.Key.ZipCode,
g.Key.Ordering
select new
{
g.Key.ZipCode,
apartCount = g.Count(p => p.a.Apartment_complex != null),
Longitude = g.Key.Longitude,
Latitude = g.Key.Latitude
}).ToArray();
Edit: Query working in sql that I want in linq2sql (very fast):
select s.ZipCode, count(distinct ident) ApartCount, b.Longitude, b.Latitude from ZipCodeServiceAvailability s
left join pdx_apart_view
on s.ZipCode = left([Zip Code], 5)
left join ZipCodeBoundaries b
on s.ZipCode = b.ZipCode
Where IsServiced = 1 and and Ordering % 10 = 0 and State = 'AL'
Group By s.ZipCode, IsServiced, b.Longitude, b.Latitude, b.Ordering
Order by s.ZipCode, b.Ordering
Original query that is very slow:
var zips = (from s in db.ZipCodeServiceAvailabilities
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode
where (s.IsServiced == service
&& b.Ordering % 10 == 0
&& s.State.Contains(state))
orderby b.ZipCode
select new
{
zipCode = b.ZipCode.Trim(),
latitude = b.Latitude,
longitude = b.Longitude,
apartCount = (from a in db.pdx_apart_views
where a.Zip_Code.Remove(5) == b.ZipCode
select a.Apartment_complex).Count()
}).ToArray();
Do you mean that you are not familiar with grouping in general, or only in the linq context?
I find it easier to write plain SQL than linq when I don't have the entity definitions, and below is what I think you are looking for in SQL - converting back to linq should be fairly straight-forward.
select
b.ZipCode zipCode,
b.Latitude latitude,
b.Longitude longitude,
count(a.Apartment_complex) apartCount
from
ZipCodeServiceAvailabilities s
join ZipCodeBoundaries b
on s.ZipCode = b.ZipCode
left join pdx_apart_views a
on substring(a.Zip_Code, 1, 5) = b.ZipCode
group by
ZipCode,
Latitude,
Longitude
There was no way to duplicate the left[(zip code), 5] sql method in linq2sql without breaking the index. The answer was to go with straight ado.net so I get all sql functionality.

How to rewrite a SQL query in LINQ to Entities?

I'm trying to rewrite a SQL query in LINQ to Entities. I'm using LINQPad with a typed datacontext from my own assembly to test things out.
The SQL query I'm trying to rewrite:
SELECT DISTINCT variantID AS setID, option_value AS name, option_value_description AS description, sort_order as sortOrder
FROM all_products_option_names AS lst
WHERE lst.optionID=14 AND lst.productID IN (SELECT productID FROM all_products_option_names
WHERE optionID=7 AND option_value IN (SELECT name FROM brands
WHERE brandID=1))
ORDER BY sortOrder;
The LINQ to Entities query I've come up with so far (which doesn't work due to a timeout error):
from a in all_products_option_names
where a.optionID == 14 && all_products_option_names.Any(x => x.productID == a.productID && x.optionID == 7 && brands.Any(y => y.name == x.option_value && y.brandID == 1))
select new
{
id = a.variantID,
name = a.option_value,
description = a.option_value_description,
sortOrder = a.sort_order,
}
This is the error I get when I run the above query: An error occurred while executing the command definition. See the inner exception for details.
And the inner exception is: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Edit:
I use MySQL and probably that's why LINQPad doesn't show me the generated SQL.
The SQL version doesn't time out.
Edit 2:
I solved the problem by completely changing the query, so this question is irrelevant now.
I marked Steven's response as the correct one, because he was closest to what i was trying to achieve and his response gave me the idea which led me to the solution.
Try this:
var brandNames =
from brand in db.Brands
where brand.ID == 1
select name;
var brandProductNames =
from p in db.all_products_option_names
where p.optionID == 7
where brandNames.Contains(p.option_value)
select p.productId;
var results =
from p in db.all_products_option_names
where p.optionID == 14
where brandProductNames.Contains(p.productId)
select new
{
setID = p.variantID,
name = p.option_value,
description = p.option_value_description,
sortOrder = p.sort_order
};
I would recommend doing joins rather than sub-select's as you have them. Sub-selects are not very efficient when you look at performance, it's like having loops inside of loops when you code , not a good idea. This could actually cause that timeout your getting if your database is running slowly even thou that looks like a simple query.
I would try using joins with a distinct at the end like this:
var results =
(from p in db.all_products_option_names
join p2 in db.all_products_option_names on p.productId equals p2.productId
join b in db.Brands on p2.option_value equals b.name
where p.optionID == 14
where p2.optionID == 7
where b.BrandID == 1
select new
{
setID = p.variantID,
name = p.option_value,
description = p.option_value_description,
sortOrder = p.sort_order
}).Distinct();
Or you could try using joins with the into and with an any like so
var results =
from p in db.all_products_option_names
join p2 in (from p3 in db.all_products_option_names.Where(x => x.optionId == 7)
join b in db.Brands.Where(x => x.BrandID == 1) on p3.option_value equals b.name
select p3) into pg
where p.optionID == 14
where pg.Any()
select new
{
setID = p.variantID,
name = p.option_value,
description = p.option_value_description,
sortOrder = p.sort_order
};

Left Join in Linq and using the variable for other joins

I am stuck with the error "value cannot be null. parameter name row" when I use Left join in Linq for DataSet.
Following is the data and the linq query.
DataRowCollection - items (Columns - Item_id, SKU, Quantity)
DataRowCollection - promotions (Columns - Item_id, Promotion_Id)
DataRowCollection - components (Columns - Component_id, Promotion_id)
DataRowCollection - amounts (Columns - Component_id, Amount_Text, currency)
var q =
from Item in items
join promotion in promotions
on Item.Field<int>("Item_id") equals promotion.Field<int?>("Item_id") into promo
from promotion in promo.DefaultIfEmpty()
join disccomponent in components
on promotion.Field<int>("Promotion_Id") equals disccomponent.Field<int?>("Promotion_Id")
join discamounts in amounts
on disccomponent.Field<int>("Component_id") equals discamounts.Field<int?>("Component_id")
where disccomponent.Field<string>("Type") == "Principal"
select new
{
SKU = Item.Field<string>("SKU"),
Quantity = Item.Field<string>("Quantity"),
DiscountAmount = discamounts.Field<string>("Amount_Text"),
DiscountCurrency = discamounts.Field<string>("currency")
};
I need to get the following:
SKU, Qty and Discount details for items which have discount
SKU, Qty for items which do not have any discount
The code worked without left outer join when all items had discount, but if any item does not have any discount it skips that item and hence I had to use the left outer join.
Any help is highly appreciated. Please let me know if any clarification is needed.
Thanks in advance.
I think you are trying to access properties on a null discamounts. Perhaps your select new should look something like this...
select new
{
SKU = Item.Field<string>("SKU"),
Quantity = Item.Field<string>("Quantity"),
DiscountAmount = discamounts == null ? "" : discamounts.Field<string>("Amount_Text"),
DiscountCurrency = discamounts == null ? "" : discamounts.Field<string>("currency")
};
Give your join a name by using into and use DefaultIfEmpty on it. Something like this (look at the last join and from expression in the statement)
var q =
from Item in items
join promotion in promotions
on Item.Field<int>("Item_id") equals promotion.Field<int?>("Item_id") into promo
from promotion in promo.DefaultIfEmpty()
join disccomponent in components
on promotion.Field<int>("Promotion_Id") equals disccomponent.Field<int?>("Promotion_Id")
join discamounts in amounts
on disccomponent.Field<int>("Component_id") equals discamounts.Field<int?>("Component_id") into DiscamountJoin
from discamount in DiscamountJoin.DefaultIfEmpty()
where disccomponent.Field<string>("Type") == "Principal"
select new
{
SKU = Item.Field<string>("SKU"),
Quantity = Item.Field<string>("Quantity"),
DiscountAmount = discamount.Field<string>("Amount_Text"),
DiscountCurrency = discamount.Field<string>("currency")
};
Thanks everyone for your help. I made this work by splitting it into 2 different linq queries below.
The first query gets the promotion data in a var
var promoData =
from promotion in promotions
join component in components
on promotion.Field<int>("Promotion_Id") equals component.Field<int?>("Promotion_Id")
join amount in amounts
on component.Field<int>("Component_id") equals amount.Field<int?>("Component_id")
where component.Field<string>("Type") == "Principal"
select new
{
Item_id = promotion.Field<int?>("Item_id"),
Promotion_id = promotion.Field<int>("Promotion_Id"),
DiscountAmount = amount == null ? "" : amount.Field<string>("Amount_Text"),
DiscountCurrency = amount == null ? "" : amount.Field<string>("currency")
};
The second query uses the promotions var to simplify the query and get the resuls
var q =
from Item in items
join promotion in promoData
on Item.Field<int>("Item_id") equals promotion.Item_id into promo
from promoJoin in promo.DefaultIfEmpty()
select new
{
SKU = Item.Field<string>("SKU"),
Quantity = Item.Field<string>("Quantity"),
DiscountAmount = promoJoin != null ? promoJoin.DiscountAmount : "0",
DiscountCurrency = promoJoin != null ? promoJoin.DiscountCurrency : ""
};
This approach works perfectly and I get all the items whether they have promotions or not. I am still thinking whether doing the same was possible in a single query :)
For now marking this as an answer, if anyone comes up with some other better way will mark that.

have join multiple table and get the output in DataRow in LINQ

HI,
I have a scenario where i have join multiple table and get the output in DataRow(All the Rows return by the query).
SQL Query:
SELECT Fr.InterCodeId
FROM
CodeShareInterline Fr,
Airline A,Zone Z #
WHERE
A.AirlineId = Fr.AirlineId
And Fr.ContractId=Z.ContractId
I know how to perform join in LINQ but how can i select all the column(Rows) in select statement of LINQ.
var result = from fr in dataContext.CodeShareInterline
from a in dataContext.AirLine
from z in dataContext.Zone
where a.AirlineId == fr.AirlineId && fr.ContractId == z.ContractId
select new
{
Interline = fr,
AirLine = a,
Zone = z
};
The anonymous type contains all data you want, you can easily visit one column by:
result.FirstOrDefault().Zone.SomeField
This is untested but something close to this should work. Assuming your data context is call Context. This is a translation of what you have above.
var o = from fr in Context.CodeShareInterline
join a from Context.Airline on a.AirlineId == fr.AirlineId
join z from Context.Zone on fr.ContactId == z.ContactId
select fr.InterCodeId;
If you want to select all of the data then you need to do something like this.
var o = from fr in Context.CodeShareInterline
join a from Context.Airline on a.AirlineId == fr.AirlineId
join z from Context.Zone on fr.ContactId == z.ContactId
select new {
Interline = fr,
AirLine = a,
Zone = z
};

Categories