linq Command not getting the answer for DB - linq

i have a table(UserQuestions) in my DB(WebSiteUsers) which contains QuestionID field as a Primary key and QuestionContext field which holds the Questions that are asked as its value.
Now i want to have a textBox that show me the QuestionContext Value by getting QuestionID.
I used these linq commands and none of them bring me the correct answer :
string Questioncontext = new WebSiteUsersEntities().UserQuestions.Where(p => p.QuestiuonID.ToString() == QuestionID).Select(p => new { p.QuestionContext}).ToString();
string Questionx = (from q in new WebSiteUsersEntities().UserQuestions where q.QuestiuonID.ToString() == QuestionID select q.QuestionContext).ToString();
QuestionCntxt.Text = Questionx;
the outcome is like this :
SELECT
[Extent1].[QuestionContext] AS [QuestionContext]
FROM [dbo].[UserQuestion] AS [Extent1]
WHERE CAST( [Extent1].[QuestiuonID] AS nvarchar(max)) = #p__linq__0

I guess your QuestionID variable is of type string, while the database column is of type int.
So rather than using
q.QuestiuonID.ToString() == QuestionID
criteria inside the query, convert the variable to int and use that as criteria.
Also ToString just gives you the SQL query text, not the result. Use ToList if you expect more than one result or FirstOrDefault if you expect zero or one results:
var questionID = int.Parse(QuestionID);
string Questioncontext = new WebSiteUsersEntities().UserQuestions
.Where(p => p.QuestiuonID == questionID)
.Select(p => p.QuestionContext)
.FirstOrDefault();
Note that I also changed the select to return directly QuestionContext string rather than anonymous object having QuestionContext property.

Related

Why is this LINQ to EF query not working?

I have a problem with the following method:
public IQueryable<Customer> ListCustomers(int? parentId)
{
Debug.Assert(parentId == null);
//var list = _customerRepository.List().Where(c => c.ParentId == null);
var list = _customerRepository.List().Where(c => c.ParentId == parentId);
return list;
}
I have one Customer in my DB with a ParentId of null. When I call the method with ListCustomers(null), list is empty for the return statement. If I swap the commented out line in and query with a hard-coded null, then list contains my one customer.
What could cause this difference between these two queries? Why is the one with c.ParentId == parentId not returning anything?
Becouse the Nullable type the linq provider will not generate the proper IS NULL check. See this answer for further information: https://stackoverflow.com/a/785501/1195510
EF translates your query with int? to something like this:
DECLARE #parentId Int = null
SELECT ... WHERE ParentId = #parentId
When this is executed on the database, it doesn't do what you expect because in SQL [column] = NULL is always false.
I agree EF could handle this better, but as a workaround, you can write something like this:
.Where( c => !parentId.HasValue
? !c.ParentId.HasValue
: c.ParentId.Value == parentId.Value
)
EF will then generate a ( somewhat verbose ) SQL statement with the correct IS NULL predicates.
with nullable types you have to use it like this:
.Where(c=> object.Equals(c.ParentId, parentId))

Distinct works on IQueryable but not List<T>?? Why?

First Table is the View and Second is the result I want
This below query works fine
List<BTWStudents> students = (from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
select new BTWStudents
{
StudentId = V.StudentId
Amount= V.PaymentMethod == "Cashier Check" ? V.Amount: "0.00"
}).Distinct().ToList();
But I changed it to List to add string formatting(see below)
List<BTWStudents> students = (from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
select new {V}).ToList().Select(x => new BTWStudents
{
StudentId = V.StudentId
Amount= V.PaymentMethod == "Cashier Check" ? String.Format("{0:c}",V.Amount): "0.00"
}).Distinct().ToList();
With this Second Query I get this
Why is distinct not working in the second query?
When working with objects (in your case a wrapped anonymous type because you are using Select new {V} rather than just Select V), Distinct calls the object.Equals when doing the comparison. Internally, this checks the object's hash code. You'll find in this case, the hash code of the two objects is different even though the fields contain the same values. To fix this, you will need to override Equals on the object type or pass a custom IEqualityComparer implementation into the Distinct overload. You should be able to find a number of examples online searching for "Distinct IEqualityComparer".
Try this (moved your distinct to the first query and corrected your bugged if/then/else):
List<BTWStudents> students = (from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
select new {V}).Distinct().ToList().Select(x => new BTWStudents
{
classId = V.Class.HasValue ? V.Class.Value : 0,
studentName = V.StudentName,
paymentAmount = V.PaymentMethod == "Cashier Check" ? String.Format("{0:c}",x.V.AmountOwed): "0.00"
}).ToList();
You can get around using Distinct all together if you Group by StudentID
var studentsGroupedByPayment =
(from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
group V by V.StudentId into groupedV
select new
{
StudentID = groupedV.Key,
Amount = string.Format("{0:C}",
groupedV.First().PaymentMethod == "Cashier Check" ?
groupedV.First().Amount : 0.0)
}
).ToList();

Linq conversion

I am using the following code to return an IList:
public IList<string> FindCodesByCountry(string country)
{
var query = from q in session.Linq<Store>()
where q.Country == country
orderby q.Code
select new {q.Code};
return (IList<string>) query.ToList();
}
However I keep getting this error:
Unable to cast object of type 'System.Collections.Generic.List1[<>f__AnonymousType01[System.String]]' to type 'System.Collections.Generic.IList`1[System.String]'.
What I am supposed to return here?
as long as q.code is a string this should work:
note that it is not creating an anonymous object, just the string is being selected.
public IList<string> FindCodesByCountry(string country)
{
var query = from q in session.Linq<Store>()
where q.Country == country
orderby q.Code
select q.Code;
return query.ToList();
}
Is there a reason you were selecting an anonymous type? If not try this...
var query = from q in session.Linq<Store>()
where q.Country == country
orderby q.Code
select q.Code;
How about
query.Select(s => s.ToString()).ToList();
Or
query.Cast<String>().ToList();
But I'm assuming that q.Code is a string? In which case you just want to change your LINQ expression:
var query = from q in session.Linq<Store>()
where q.Country == country
orderby q.Code
select q.Code;
In the query, instead of selecting an anonymous class containing a string, just select the string itself:
var query = from q in session.Linq<Store>()
where q.Country == country
orderby q.Code
select q.Code;
You can't cast a list of custom types to a list of strings like that. The easiest way would be to have your query object begin it's life as an iEnumerable list of strings, rather than a custom type. Change your select line to:
select new q.Code.toString();
and you'll be good. If q.Code is itself a string to begin with, then the .ToString() won't be necessary.
Try this:
return query.ToList<string>();

Conditional Multiple Fields Searching and Filtering in LINQ

Assuming that we have the following table:
Person:
PersonID,
Name,
Age,
Gender
And we are providing a search function that allows users to search the table according to the name and/or the age.
The tricky part in writing the SQL ( or LINQ) query is that the users can choose to search for both field, or any one field, or no field. If he wants to search for all then he would just have to leave the textbox blank.
The logic to do this can be written as follows:
var p;
if(Name_TextBox=='')
{
p=from row in person
select row ;
}
else
{
p= from row in person
where row.Name=Name_TextBox
select row ;
}
// repeat the same for age
Now after a while the code gets very long and messy... How can I compress the above into a single query with no if-else?
Try code like this
string personName = txtPersonName.Text;
int personAge = Convert.ToInt32(txtAge.Text);
var opportunites = from p in this.DataContext.Persons
select new
{
p.PersonID,
p.Name,
p.Age,
p.Gender
};
if (personsID != 0)
opportunites = opportunites.Where(p => p.PersonID == personID);
if (personName != string.Empty)
opportunites = opportunites.Where(p => p.Name.StartsWith(personName));
if (personAge != 0)
opportunites = opportunites.Where(p => p.Age == personAge);
This will work fine. If personName is not given it will be not add to where, and if given then it will added.
One alternative which I have used in SQL which could be implemented in Linq too is
var p = from p in Person
where p.Name == Name_TextBox || Name_TextBox == String.Empty
select p;
(Note that your 'linq' is using SQL syntax, which won't compile. Also you can't declare a var as you are doing without directly assigning a value)
why not use the null coalescing operator? eg.
var products = from a in context.products
where a.ID == (productID ?? a.ID)
select a;
This works really well on my system

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