c# lambda expression convert from vb to c# - c#

I'm trying to convert this vb.net code to c#.
If (txtCompanyName.Text.Trim() <> String.Empty) Then
decals = decals.Where(Function(d As CT_Decal) (From c In db.CT_Companies Where c.CompanyName.Contains(txtCompanyName.Text.Trim()) Select c.CompanyID).ToList.Contains((From t In db.CT_Tanks Where t.CargoTankID = d.TankID Select t.CompanyID).Single.ToString()))
End If
In c# I tried to put the code:
if (txtCompanyName.Text.Trim() != string.Empty)
{
decals = decals.Where(Function(CT_Decal d)(from c in db.CT_Companies
where c.CompanyName.Contains(txtCompanyName.Text.Trim())
select c.CompanyID).ToList().Contains((from t in db.CT_Tanks where t.CargoTankID == d.TankID
select t.CompanyID).Single.ToString()));
}//end if
c# errors:
The name function does not exist and
CT_Decal is a type but is used like a variable.
Does anybody know how to convert this properly?

Without access to your DBContext it's hard to give you an exact query, ignoring the inefficiency of the query you're using.
From what we have, I expect the following code gets pretty close to what you want, or at least should get you started:
if (!String.IsNullOrWhiteSpace(txtCompanyName.Text))
{
var result =
decals.Where(
d => (
from c in db.CT_Companies
where c.CompanyName.Contains(txtCompanyName.Text.Trim())
select c.CompanyID
).Contains(
(from t in db.CT_Tanks where t.CargoTankID == d.TankID select t.CompanyID).Single()));
I expect this will function exactly the same if you've setup your DBContext correctly:
if (!String.IsNullOrWhiteSpace(txtCompanyName.Text))
{
IEnumerable<Decal> result =
decals.Where(d => string.Equals(d.Tank.Company.CompanyName, txtCompanyName.Text.Trim());

your problem is in the keyword function within the where clause.
You must write something like this .Where(d=>(....)). Please see 'jessehouwing' reply.
The syntax .Where(function(f) ....) is a VB.Net equivalent of the lambda expression in C#.
The lambda expression .Where(d => (...)) means 'd' goes to (some action or expression ).
Let me know if this helps.

Related

LINQ nested array and the ternary operator. The nested query is not supported. Operation1='Case' Operation2='Collect'

The following code produces the error
The nested query is not supported. Operation1='Case' Operation2='Collect'
The question is what am i doing so terribly wrong? How can i fix that?
IQueryable<Map.League> v = from ul in userLeagues
select new Map.League
{
id = ul.LeagueID,
seasons =
inc.Seasons ? (from ss in ul.Standings
where ss.LeagueID == ul.LeagueID
select new Map.Season
{
seasonId = ss.Season.SeasonId,
seasonName = ss.Season.SeasonName
}).ToList() : null,
};
Update
what i cannot follow is why this is working as a charm
seasons = (from ss in ul.Standings
where ss.LeagueID == ul.LeagueID
select new Map.Season
{
seasonId = ss.Season.SeasonId,
seasonName = ss.Season.SeasonName
}).Distinct(),
what is wrong with the ternary operator?
The exception indicates that you're using Entity Framework. Always good to mention the LINQ implementation in questions.
When LINQ runs against a SQL backend, the SQL provider tries to translate the whole statement into one SQL statement. This greatly reduces the types of operations that are supported, because SQL is far more restricted than LINQ. Note that the variable inc.Seasons should also part of the SQL statement. Now the problem is that a SQL can't return two different result set depending on a variable that's part of itself: there is always one fixed SELECT clause.
So there is a Case method in the expression in a place where it's not supported (and I guess that hence the subsequent Collect isn't supported either).
You could solve this by making the inclusion part of the where clause:
from ul in userLeagues
select new Map.League
{
id = ul.LeagueID,
seasons = from ss in ul.Standings
where inc.Seasons // here
&& ss.LeagueID == ul.LeagueID
select new Map.Season
{
seasonId = ss.Season.SeasonId,
seasonName = ss.Season.SeasonName
})
}
I think you simply can't put an if-else inside a linq query, at least not in that spot.
See this post for detailed explanation and discussion.
Oh, and specially look at the "hack" by user AyCabron, I think that could resolve your situation neatly (depending on what you exactly want and why you choose to have null pointers).
The problem is not with Linq in general but with Linq to objects.
since you are using IQueryable you expect the query to run in the DB,
in that context, you cannot use many operators including the ternary operator.
if you tried the same code using Linq to objects (i.e Enumerable) it will succeed.
see example here: working example
Error The nested query is not supported. Operation1='Case' Operation2='Collect' is generated by EF when you use null within a ? statement.
EF can not convert statements like condition ? object/list : null.
In your specific example, remove .ToList() as it will also produce error when there is no rows return. EF will automatically give you null when there is no items to select.

Cannot convert lambda expression to type 'bool' because it is not a delegate type

The following returns Cannot convert lambda expression to type 'bool' because it is not a delegate type
var Products = from s in db.Products where
( from c in s.Manufacturers
where (x => (from man in model.man where man.HasValue select man.Value).Contains(c.ManufacturerID)
select c).Any()
select s;
While this just works
if (model.man != null)
{
var students = from s in db.Products
where (from c in s.Manufacturers
where model.man.Contains(c.ManufacturerID)
select c).Any()
select s;
}
What am i doing wrong in the first case?
The model.man is declared as
public int?[] man { get; set; }
You can use null conditional access instead (in C# 6)
var students = from s in db.Products
where (from c in s.Manufacturers
where model.man?.Contains(c.ManufacturerID) ?? false
select c).Any()
select s;
Edit: added ?? false because there is no implicit conversion between bool and bool?
Like Rahul says, you cannot mix query and method syntax. This should compile:
var Products = from s in db.Products
where(from c in s.Manufacturers
where (from man in model.man
where man.HasValue
select man.Value)
.Contains(c.ManufacturerID)
select c).Any()
select s;
If you want to use a lambda expression at that particular point, you can always chain it with a period, e.g.:
var Products = from s in db.Products
where(s.Manufacturers
.Where(c => (from man in model.man
where man.HasValue
select man.Value)
.Contains(c.ManufacturerID))).Any()
select s;
Although as personal preference (readability), I'd rather not mix the two syntaxes. If you are unfamiliar with method syntax, ReSharper does provide the option to convert query to method chain (hammer icon).
I too got the same error in a simple for loop. The error was due to the misplaced "=" symbol.
It was
for(int i=10;i=>0;i--)
{
//your code
}
If you look at the code closely you can see that = is placed in front of >.
It should be less than or equal to that is >=.
The correct code should be
for(int i=10;i>=0;i--)
{
//your code
}
I hope this might help someone.

Linq to SQL - Query

I am trying to mimic below statement in Linq to SQL.
WHERE (rtrim(posid) like '%101' or rtrim(posid) like '%532')
I statement basically determine if posid ends with 101 or 532. In the above example I am only making 2 comparisons but their could be 1 to N comparisons all joined with OR. I store the comparison values (101,532,...) in a generic list that I send to my Linq to SQL method.
I have tried to mimic above SQL using a where clause unsuccessfully (example below):
var PosNum = new List<string>();
PosNum.Add("101");
PosNum.Add("532");
var q = (from a in context.tbl_sspos select a);
q = q.Where(p => PosNum.Contains(p.posid.Trim()));
The issue with the above where clause is that it tries to do an exact match rather I want an ends with comparison.
How would I mimic the SQL statement in Linq to SQL.
Thank You in advance for any help / advice you can provide.
I would use String.EndsWith();
This will check the end of the string rather than entire contents of it.
var q = (from a in context.tbl_sspos select a);
q = q.Where(p => p.posid.EndsWith("102") || p.posid.EndsWith("532"));
In EF 4 you can use the StartsWith / EndsWith methods by now. Might also work in LINQ to SQL.
UPDATE
Just realized that you are trying todo this against multiple values (PosNum), I don't think that this is directly supported currently. You can however concatenate multiple Where()clauses to get the result.
UPDATE 2
As AdamKing pointed out concatenating the where clauses was filtering against all PosNum values, here is the corrected version:
var baseQuery = (from a in context.tbl_sspos select a);
IEnumerable<YourType> q = null;
foreach(var pos in PosNum)
{
if(q == null)
q = baseQuery.Where(a => a.posid.EndsWith(pos));
else
q = q.Union(baseQuery.Where(a => a.posid.EndsWith(pos)));
}
This is not as pretty anymore, but works nonetheless.

Convert code snippet from VB.NET to C#

I have tried a number of freely available code converters to convert the following piece, however without success.
Dim resultList = ((From e In p_Xml.Elements()
Where UCase(e.Name.LocalName) = searchName).Union(
From a In p_Xml.Attributes()
Where UCase(a.Name.LocalName) = searchName
Select <<%= propertyName %>><%= a.Value %></>)).ToList()
I think I got it here
var resultList = (from e in p_xml.Elements()
where e.Name.LocalName == searchName
select propertyName).
Union(from a in p_xml.Attributes()
where a.Name.LocalName == searchName
select a.Value).ToList();
Your conversion left out UCase, whose equivalent in C# is ToUpperCase.
This is not the recommended way to perform case-insensitive string comparisons, though.
e.Name.LocalName == searchName
should be replaced with something like:
String.Compare(e.Name.LocalName, searchNamename, StringComparison.InvariantCultureIgnoreCase) == 0
Also, what is propertyName? Whatever it is, its value is obviously not dependent on e. You're selecting one and the same thing for every e in your first query, which makes no sense. I guess you meant select e.
What you probably want then is something along the lines of:
var resultList = (from e in p_xml.Elements()
where String.Compare(e.Name.LocalName, searchName, StringComparison.InvariantCultureIgnoreCase) == 0
select e).
Union(from a in p_xml.Attributes()
where String.Compare(a.Name.LocalName, searchName, StringComparison.InvariantCultureIgnoreCase) == 0
select a.Value).ToList();
I'm only not sure how to represent Select <<%= propertyName %>><%= a.Value %></> in C#, since I don't know VB.
I heard from Microsoft's Roslyn project in a presentation. Maybe that can help you.
Microsoft want to integrate Roslyn in a future Visual Studio version. Then it would be possible to just copy code from VB to clipboard and paste it as C# code. There was also a presentation about that in last year, maybe the same one.
Good online Code Converter that I use all the time is http://www.developerfusion.com/tools/convert/vb-to-csharp/

Are ternary operators not valid for linq-to-sql queries?

I am trying to display a nullable date time in my JSON response. In my MVC Controller I am running the following query:
var requests =
(from r in _context.TestRequests
where r.scheduled_time == null && r.TestRequestRuns.Count > 0
select new
{
id = r.id,
name = r.name,
start = DateAndTimeDisplayString(r.TestRequestRuns.First().start_dt),
end = r.TestRequestRuns.First().end_dt.HasValue
? DateAndTimeDisplayString(r.TestRequestRuns.First().end_dt.Value)
: string.Empty
});
When I run requests.ToArray() I get the following exception:
Could not translate expression '
Table(TestRequest)
.Where(r =>
((r.scheduled_time == null) AndAlso (r.TestRequestRuns.Count > 0)))
.Select(r => new <>f__AnonymousType18`4(id = r.id, name = r.name,
start = value(QAWebTools.Controllers.TestRequestsController).
DateAndTimeDisplayString(r.TestRequestRuns.First().start_dt),
end = IIF(r.TestRequestRuns.First().end_dt.HasValue,
value(QAWebTools.Controllers.TestRequestsController).
DateAndTimeDisplayString(r.TestRequestRuns.First().end_dt.Value),
Invoke(value(System.Func`1[System.String])))))'
into SQL and could not treat it as a local expression.
If I comment out the end = line, everything seems to run correctly, so it doesn't seem to be the use of my local DateAndTimeDisplayString method, so the only thing I can think of is Linq to Sql doesn't like Ternary operators? I think I've used ternary operators before, but I can't remember if I did it in this code base or another code base (that uses EF4 instead of L2S).
Is this true, or am I missing some other issue?
Modify the DateAndTimeDisplayString to accept a different argument type and have a query like this:
end = DateAndTimeDisplayString(r.TestRequestRuns.FirstOrDefault())
This way, you can do the ternary stuff in your code.
By the way, it's actually this part which looks bad, because the ternary gets translated to IIF and seems to be handled, maybe try a null string:
Invoke(value(System.Func`1[System.String])))))
Have you considered using the Null coalescing operationg? (??)
Your code would then look like this:
end = r.TestRequestRuns.First().end_dt ?? string.Empty
You could modify your DateAndTimeDisplayString method to return null if passed null.

Categories