differences in LINQ queries - linq

Can someone explain why, when a query should be returning one string item only like in the example below;
From c in context.Products Where c.Id=prodId Select c.Name
Why cant that be done like so;
Dim prodDeleted as String = (From c in context.Products Where c.Id=prodId Select c.Name).ToString()
bvecause it returns this (System.Data.Objects.ObjectQuery`1[System.String]) , instead of the product name
versus having to do it like so;
Dim prodDeleted = (From c In ctx.products
Where c.Id = prodId
Select c).FirstOrDefault()
Dim deletedprodname As String = prodDeleted.Name.ToString()

Because all calls to Select return an IEnumerable rather than a single element.
To verify that your query really returns a single element, you need to add the call to Single. Or, if you don't care if a single element or multiple elements were returned, you can grab the first using First.
If you're not against using the VB.NET equivalent of lambda syntax, you can streamline everything:
Dim deletedProdName As String =
ctx.products.SingleOrDefault(Function(c) c.Id = prodId).Name

Related

LINQ Query Variable passed to Another LINQ Query

What is the difference between the query in this post:
Save LINQ Query As Variable To Call Another LINQ Query
var parentLoc = (from a in db.PartsLocations
where a.LocationName == aContainer
select a.ParentLocation);
var locations = (from b in db.PartsLocations
where b.LocationID == parentLoc
select b).ToList();
to the following example from this post.
Dim persVogel = From p In db.People
Where p.LastName = "Vogel"
Select p
Dim persVogelPHVIS = From pp In persVogel
Where pp.Company.Name = "PHVIS"
Select pp
Both of these have declared 2 queries and use the first query variable into second query.
What is the reason to use Single() in the first example but was not used in visualstudiomagazine.com article? Thanks
The two samples are fundamentally different.
First Sample
I think you pasted this one incorrectly...from the referenced question, the query should be:
var parentLoc = (from a in db.PartsLocations
where a.LocationName == aContainer
select a.ParentLocation).Single();
var locations = (from b in db.PartsLocations
where b.LocationID == parentLoc
select b).ToList();
(I am going to assume that LocationID and ParentLocation are typed as int.)
In this sample parentLoc is an int - a single instance of a ParentLocation value, obtained from the PartsLocations table. So what you get is an int.
The second linq statement sources its records also from the PartsLocations table. It uses parentLoc to identify records within that table (e.g. where b.LocationID == parentLoc). What you get at the end is a set of PartsLocations records.
The .Single() call is made because you want to compare the result to LocationID in the second statement, and cannot compare int to IEnumerable<int>.
Second Sample
Dim persVogel = From p In db.People
Where p.LastName = "Vogel"
Select p
Dim persVogelPHVIS = From pp In persVogel
Where pp.Company.Name = "PHVIS"
Select pp
In the second sample, persVogel is a subset of records from the People table (specifically, the subset of people with LastName == "Vogel") - so what you get is a set of People records.
The second linq statement is based on this subset of records (From pp In persVogel) and further filters them down to records where pp.Company.Name = "PHVIS". What you get is still a set of People records.
These two statements could easily be compressed into one single statement:
Dim persVogelPHVIS = From p In db.People
Where p.LastName = "Vogel"
AndAlso p.Company.Name = "PHVIS"
Select p
You will still get a set of People records at the end.

How do I use Like in Linq Query?

How I can use Like query in LINQ ....
in sql for eg..
name like='apple';
thanks..
Use normal .NET methods. For example:
var query = from person in people
where person.Name.StartsWith("apple") // equivalent to LIKE 'apple%'
select person;
(Or EndsWith, or Contains.) LINQ to SQL will translate these into the appropriate SQL.
This will work in dot notation as well - there's nothing magic about query expressions:
// Will find New York
var query = cities.Where(city => city.Name.EndsWith("York"));
You need to use StartsWith, Contains or EndsWith depending on where your string can appear. For example:
var query = from c in ctx.Customers
where c.City.StartsWith("Lo")
select c;
will find all cities that start with "Lo" (e.g. London).
var query = from c in ctx.Customers
where c.City.Contains("York")
select c;
will find all cities that contain "York" (e.g. New York, Yorktown)
Source
name.contains("apple");
I use item.Contains("criteria"), but, it works efficiently only if you convert to lower both, criteria and item like this:
string criteria = txtSearchItemCriteria.Text.ToLower();
IEnumerable<Item> result = items.Where(x => x.Name.ToLower().Contains(criteria));

Need help with designing a query in ELinq

This is my query:
Dim vendorId = 1, categoryId = 1
Dim styles = From style In My.Context.Styles.Include("Vendor") _
Where style.Vendor.VendorId = vendorId _
AndAlso (From si In style.StyleItems _
Where si.Item.Group.Category.CategoryId = _
categoryId).Count > 0 _
Distinct
I have the feeling that I can improve the performance, cuz the above query is (correct me if I am wrong) performs 2 round-trips to the server; 1 time by the Count and then when it's executed.
I want to send this Count thing to the DB so it should be only one round trip to the server.
Even it's not the exact thing, this is actually what I need:
SELECT DISTINCT Style.*
FROM Style INNER JOIN
Vendor ON Style.VendorId = Vendor.VendorId INNER JOIN
StyleItem ON Style.StyleId = StyleItem.StyleId INNER JOIN
Item ON StyleItem.ItemId = Item.ItemId INNER JOIN
[Group] ON Item.GroupId = [Group].GroupId INNER JOIN
Category ON [Group].CategoryId = Category.CategoryId
WHERE (Style.VendorId = #vendorid) AND (Category.CategoryId = #CategoryId)
I wish I could use this SPROC (i.e. function import etc.), but I need to Include("Vendor"), which constraints me to do it with Linq.
Any kind of suggestion will be really welcommed!
It is probably not doing two trips to the database. It will get optimized before it is executed, and nothing gets executed until you try the read the data.
Normally I check the SQL that is created using SQL Profiler. I have also found LinqPad to be very usefull.

Can Distinct be expressed using so-called embedded query rather than a method call

given the following code:
string[] colors = {"red","green","blue","red","green","blue"};
var distinctColors = (from c in colors select c).Distinct();
distinctColors.Dump();
Is it possible to fold the call .Distinct() into the embedded query syntax?
something like int T-SQL
select distinct color from TableofColors
C#'s query expression syntax doesn't include "distinct". VB's does, however - for example, from the MSDN docs for VB's Distinct clause:
// VB
Dim customerOrders = From cust In customers, ord In orders _
Where cust.CustomerID = ord.CustomerID _
Select cust.CompanyName, ord.OrderDate _
Distinct
The C# equivalent would have to explicitly call Distinct() in dot notation.
However, your example can still be simplified:
string[] colors = {"red","green","blue","red","green","blue"};
var distinctColors = colors.Distinct();
distinctColors.Dump();
Don't think you have to use query expressions to use LINQ :)
There's no distinct embedded query syntax in C# as far as I'm aware. This is as close as it gets:
var distinctColors = (from color in colors
select color).Distinct()
Query comprehension syntax does not support the Distinct method.
In your case, you could simply write colors.Distinct(); you're not doing anything with the query expression.
You can try this
var dis = from c in colors
group c by c;
foreach (var cVal in dis)
{
string s = cVal.Key;
}

What is the correct way of reading single line of data by using Linq to SQL?

I'm very new to Linq, I can find multi-line data reading examples everywhere (by using foreach()), but what is the correct way of reading a single line of data? Like a classic Product Detail page.
Below is what I tried:
var q = from c in db.Products
where c.ProductId == ProductId
select new { c.ProductName, c.ProductDescription, c.ProductPrice, c.ProductDate };
string strProductName = q.First().ProductName.ToString();
string strProductDescription = q.First().ProductDescription.ToString();
string strProductPrice = q.First().ProductPrice.ToString();
string strProductDate = q.First().ProductDate.ToString();
The code looks good to me, but when I see the actual SQL expressions generated by using SQL Profiler, it makes me scared! The program executed four Sql expressions and they are exactly the same!
Because I'm reading four columns from a single line. I think I must did something wrong, so I was wondering what is the right way of doing this?
Thanks!
Using the First() extension method would throw the System.InvalidOperationException when no element in a sequence satisfies a specified condition.
If you use the FirstOrDefault() extension method, you can test against the returned object to see if it's null or not.
FirstOrDefault returns the first element of a sequence, or a default value if the sequence contains no elements; in this case the default value of a Product should be null. Attempting to access the properties on this null object will throw ArgumentNullException
var q = (from c in db.Products
where c.ProductId == ProductId
select new { c.ProductName, c.ProductDescription, c.ProductPrice, c.ProductDate }).FirstOrDefault();
if (q != null)
{
string strProductName = q.ProductName;
string strProductDescription = q.ProductDescription;
string strProductPrice = q.ProductPrice;
string strProductDate = q.ProductDate;
}
Also, you shouldn't have to cast each Property ToString() if you're object model is setup correctly. ProductName, ProductDescription, etc.. should already be a string.
The reason you're getting 4 separate sql queries, is because each time you call q.First().<PropertyHere> linq is generating a new Query.
var q = (from c in db.Products
where c.ProductId == ProductId
select new { c.ProductName, c.ProductDescription, c.ProductPrice, c.ProductDate }
).First ();
string strProductName = q.ProductName.ToString();
string strProductDescription = q.ProductDescription.ToString();
string strProductPrice = q.ProductPrice.ToString();
string strProductDate = q.ProductDate.ToString();

Resources