If Statement inside LINQ Select Query - linq

I has a table call Staff and has two field call StaffStatus and ParentStatus. I would like to display the Status as "Available" when StaffStatus AND ParentStatus are both "Available" and display the Status as "Unavailable" when either StaffStaus OR ParentStatus is "Unavailable".
Friend Function getAllUser(strInput As String) As IQueryable
getAllUser = From userDB In db.Staffs
Select Status = userDB.UserStatus.Equals("Available") And userDB.ParentStatus.Equals("Available") ? "Available" : (userDB.UserStatus.Equals("Unavailable") Or userDB.ParentStatus.Equals("Unavailable") ? "Unavailable")
End Function
But the code editor show : The character "?" cannot be used here and the Syntax error of first "(" at ": (userDB.UserStatus.Equals("Unavailable")". Any error with my code?

Simply: There is no ternary operator (as you use it) in VB.NET
Take a look at here: Is there a conditional ternary operator in VB.NET?
You have to use a Dim foo as String = If(bar = uz, cat, dog) construct
Edit:
Try this
Dim getAllUser = From userDb In db.Staffs
Select New Staff() With
{
.UserStatus = If(userDb.UserStatus.Equals("Available") And userDb.ParentStatus.Equals("Available"), "Available", If(userDb.UserStatus.Equals("Unavailable") Or userDb.ParentStatus.Equals("Unavailable"), "Unavailable", "SomeOtherValue"))
}

Related

How to check "Is Nothing" in Linq dynamic query

I'm trying to check a very basic expression with Linq dynamic queries.
Although this woks perfectly with regular Linq.
Dim xxx = From x In db.Users Where x.AgentID Is Nothing Select x.FirstName, x.LastName
it seems not to work with dynamic queries:
Dim xx = db.Users.Where("AgentID Is Nothing").ToList
I get this error:
Boolean expression expected
What am I doing wrong ?
You must have a Boolean expression not a string to get the result like:
Dim xx = db.Users.Where(u=>u.AgentID==null).ToList()
I found following solution :
"AgentID.HasValue = False"

Accessing anonymous types returned via a dynamic link query

I have been trying to access the data returned from a dynamic linq query as an anonymous type. The advice I have found suggests that I should create a custom type and use it in the Select clause with the new keyword. I was directed to the followed Question for a code example:
System.LINQ.Dynamic: Select(" new (...)") into a List<T> (or any other enumerable collection of <T>)
This was indeed an excellent example which I incorporated into my code (which is VB so I had to do some translation).
My code compiles fine but When I run it , I get the error following error:
"Value cannot be null. Parameter name: member" at the following line from the example:
bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
This seems to be linked to expressions(i), which correctly contains two items as I am returning two fields from the database table. properties(i) holds the name of those two fields correctly. Any ideas as to what the value for member is supposed to be and where it should be found? Is it something from the database?
The where clause of this query works and when I run it as an anonymous type it brings back records (or rather two fields from records). The returned fields contain data not nulls.
Here is my VB version of the code from the example provided in the earlier Question. I have bolded or ** the line where the error occurs. Any ideas as to what is causing this?
Much appreciated.
Function ParseNew() As Expression
NextToken()
ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)
NextToken()
Dim properties As New List(Of DynamicProperty)()
Dim expressions As New List(Of Expression)()
Do
Dim exprPos = tokenVal.pos
Dim expr = ParseExpression()
Dim propName As String
If TokenIdentifierIs("as") Then
NextToken()
propName = GetIdentifier()
NextToken()
Else
Dim [me] As MemberExpression = TryCast(expr, MemberExpression)
If [me] Is Nothing Then Throw ParseError(exprPos, Res.MissingAsClause)
propName = [me].Member.Name
End If
expressions.Add(expr)
properties.Add(New DynamicProperty(propName, expr.Type))
If tokenVal.id <> TokenId.Comma Then Exit Do
NextToken()
Loop
ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected)
NextToken()
'CODE added to support strongly-typed returns
Dim type As Type = If(newResultType, DynamicExpression.CreateClass(properties))
Dim bindings(properties.Count - 1) As MemberBinding
For i As Integer = 0 To bindings.Length - 1
**bindings(i) = Expression.Bind(type.GetProperty(properties(i).Name), expressions(i))**
Next
Return Expression.MemberInit(Expression.[New](type), bindings)
End Function

Linq to datasets - getting specific column value in C#

i'm trying to get an error description according to error Id:
String errorDesc = from resultCodesTableRow in resultCodesDT.AsEnumerable()
where resultCodesTableRow.Field<int>("Error_Code_Column_Name") == errorCode
select resultCodesTableRow.Field<string>("Error_Desc_Column_Name").ToString();
why do i get the error:
"Cannot implicitly convert type 'System.Data.EnumerableRowCollection' to 'string'" ?
how does the query supposed to look ?
Change
resultCodesDT.AsEnumerable() to resultCodesDT.rows
Does this work:
where (int)resultCodesTableRow.GetItem("Error_Code_Column_Name") == errorCode
select resultCodesTableRow.GetItem("Error_Desc_Column_Name")
I am not pretty sure what the actual LINQ query is returning most probably by seeing it and as you said you are getting error it might be returning a Collection so in order to avoid use first or last method to the query ie
String errorDesc = from resultCodesTableRow in resultCodesDT.AsEnumerable()
where resultCodesTableRow.Field("Error_Code_Column_Name") == errorCode
select resultCodesTableRow.Field("Error_Desc_Column_Name").First().ToString();
the Select function in your statement will return an IEnumerable.
instead you need to use something like
String errorDesc = (from resultCodesTableRow in resultCodesDT.AsEnumerable()
where resultCodesTableRow.Field<int>("Error_Code_Column_Name") == errorCode
select resultCodesTableRow.Field<string>("Error_Desc_Column_Name").ToString()).First();
or maybe this would work but is untested
String errorDesc = resultCodesDT.Where(X=> x.Error_Code_Column_Name==errorCode)
.Select(s=>s.Error_Desc_Column_Name.toString()).First();

Building Dynamic LINQ Queries based on Combobox Value

I have a combo box in Silverlight. It has a collection of values built out of the properties of one of my LINQ-to-SQL objects (ie Name, Address, Age, etc...). I would like to filter my results based off the value selected in a combo box.
Example: Say I want everyone with a last name "Smith". I'd select 'Last Name' from the drop down list and enter smith into a textbox control. Normally I would write a LINQ query similar to...
var query = from p in collection where p.LastName == textbox.Text select p;
Is it possible to decide the property dynamically, maybe using Reflection? Something like
var query = from p in collection where p.(DropDownValue) == textbox.Text select p;
Assuming:
public class Person
{
public string LastName { get; set; }
}
IQueryable<Person> collection;
your query:
var query =
from p in collection
where p.LastName == textBox.Text
select p;
means the same as:
var query = collection.Where(p => p.LastName == textBox.Text);
which the compiler translates from an extension method to:
var query = Queryable.Where(collection, p => p.LastName == textBox.Text);
The second parameter of Queryable.Where is an Expression<Func<Person, bool>>. The compiler understands the Expression<> type and generates code to build an expression tree representing the lambda:
using System.Linq.Expressions;
var query = Queryable.Where(
collection,
Expression.Lambda<Func<Person, bool>>(
Expression.Equal(
Expression.MakeMemberAccess(
Expression.Parameter(typeof(Person), "p"),
typeof(Person).GetProperty("LastName")),
Expression.MakeMemberAccess(
Expression.Constant(textBox),
typeof(TextBox).GetProperty("Text"))),
Expression.Parameter(typeof(Person), "p"));
That is what the query syntax means.
You are free to call these methods yourself. To change the compared property, replace this:
typeof(Person).GetProperty("LastName")
with:
typeof(Person).GetProperty(dropDown.SelectedValue);
Scott Guthrie has a short series on dyamically built LINQ to SQL queries:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
That's the easy way...then there's another way that's a bit more involved:
http://www.albahari.com/nutshell/predicatebuilder.aspx
You can also use the library I created: http://tomasp.net/blog/dynamic-linq-queries.aspx. You would store the properties in ComboBox as lambda expressions and then just write:
var f = (Expression<Func<Product, string>>)comboBox.SelectedValue;
var query =
from p in collection
where f.Expand(textBox.Text)
select p;

Linq Error: InvalidOperationException: Could not translate expression

Get value out of DateTime column
if null to return String.Empty
else
DateTime.ToShortDateString
What am I doing wrong => query produced below:
var queryable = from p in Products
select new {
selldate = p.SellEndDate == null
? string.Empty
: p.SellEndDate.Value.ToShortDateString() };
Error: InvalidOperationException: Could not translate expression 'Table(Product).Select(p => new <>f__AnonymousType01(selldate = IIF((p.SellEndDate = null), Invoke(value(System.Func1[System.String])), p.SellEndDate.Value.ToShortDateString())))' into SQL and could not treat it as a local expression.
Basically what's happening here is that LINQ to SQL is taking your entire query and trying to convert it into something that SQL Server can understand. The problem, though, is that SQL Server has no concept of DateTime.ToShortDateString, so the conversion to SQL fails.
You'll have to change your query so that it just selects SellEndDate (which will get it as a Nullable<DateTime>) and then when you use the results of that query you can do the conversion to string. For example:
var list = (from p in Products
select p.SellEndDate).ToList();
// calling ToList() above means we have the entire resultset in memory and
// no longer have to pass the query back to SQL Server
var stuff = from p in list select new
{
selldate = p.SellEndDate == null ?
string.Empty :
p.SellEndDate.Value.ToShortDateString()
};
ToShortDateString doesn't seem to have equivalent SQL translation.
Use ToString instead.
If the date time field allows nulls:
from order in repository.Order
select order.OrdShipDate == null ? "" : order.OrdShipDate.GetValueOrDefault(DateTime.Now).Month.ToString() + "/" + order.OrdShipDate.GetValueOrDefault(DateTime.Now).Day.ToString() + "/" + order.OrdShipDate.GetValueOrDefault(DateTime.Now).Year.ToString();
If the date time field doesn't allow nulls:
from order in repository.Order
select order.OrdShipDate.Month.ToString() + "/" + order.OrdShipDate.Day.ToString() + "/" + order.OrdShipDate.Year.ToString();

Resources