Concatenate string in Linq query - c#

I have a db call that returns me an object. I use linq to cast that object how I want it
var result = queryResult.OrderBy(c => c.TariffName)
.Take(count)
.Select(c => new
{
Text = c.TariffName,
Key = c.TariffId,
Price = c.LineRental
});
var list = result.ToList();
I now want to add the line rental to the tariff name show that it shows like:
myTariff - 12.99
when I try and do this though I can make this change ok:
Text = c.TariffName + " - ",
but when I try and add the line rental I get problems that linq won't recognise the ToString(). I need it to look like:
Text = c.TariffName + " - " + c.LineRental.ToString(),
I understand that linq won't recognise the ToString() method from reading LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression but how do I change this given I can't set it as a string prior to the linq query?

Convert the query result to a list first then use select to make the toString work.
var result = queryResult.OrderBy(c => c.TariffName)
.Take(count);
var list = result.ToList().Select(c => new
{
Text = c.TariffName + " - " + c.LineRental.ToString(),
Key = c.TariffId,
Price = c.LineRental
});

What is happening linq trying to execute your select statement on the database query level, and it does not know how to transform your .Select lambda to select part of sql statement.
Easiest thing you can do is first query required fields, call .ToList() on query to execute it and perform projection after that.
var result = queryResult.OrderBy(c => c.TariffName)
.Take(count)
.Select(c => new
{
Text = c.TariffName,
Key = c.TariffId,
Price = c.LineRental
});
var list = result.ToList().Select(c=>new {
Text = string.Format("{0} - {1}", c.Text, c.Price),
Key=Key,
Price=Price
});

Related

find and replace result of a list with linq

Is there a way to replace the value of one result with another after doing a linq statement?
is that in my linq statement in ** Status **, there are some that come to me with this result "PendingForApprover" but I want to replace it with "Pending for approver", I would like that after obtaining the result, you can use a find and based on that replace the values, before in my model I had it with a data annotation with a display name but for the reason that that result I am going to transform it into JSON and then it will be brought by server side that method is not working
y share my sentence LINQ
var result = db.document.Select(d => new DocumentViewModel
{
DocumentId = d.DocumentId,
Name = w.name
ReceivedLogs = d.Logs
Status = w.Status.toString(),
.Where(l => l.Status == Status.Received)
.Select(l => new LogViewModel
{
CurrentApprover = l.User,
NameApprover = l.User.FullName
}).FirstOrDefault()
}).ToList();
thanks
Have you tried with Switch expressions it is a pretty clear solution and you can integrate it in your LINQ query.
Status = w.Status switch
{
Status.StatusOne => "Status One",
Status.PendingForApprover => "Pending for approver",
_ => "Unknown"
}

Converting linq select into model, LINQ to Entities does not recognize the method, and this method cannot be translated into a store expression

Hi I i'm doing this linq expression in an web api but then it gives this error
LINQ to Entities does not recognize the method 'WebApplicationAPI.Models.Registo convertToRegisto(WebApplicationAPI.Models.TBS0017)' method, and this method cannot be translated into a store expression.
Here's the code:
var tBS0017 = from row in db.TBS0017
where row.Cartao == cartao && row.Data == data
var teste = tBS0017.Select(x => convertToRegisto(x));
public Registo convertToRegisto(TBS0017 x)
{
string term = db.ba_terminal.Where(y => "00"+y.terminal_id.ToString() == x.CodTerminal).Select(y => y.terminal_name).ToString();
string emp = db.TG0006.Where(y => "00"+y.IdCompanhia.ToString() == x.IdCompanhia.ToString()).Select(y => y.DsCompanhia).ToString();
Registo r = new Registo() { Cartao = x.Cartao, Data = x.Data, Hora = x.Hora, Local = term, Empresa = emp };
return r;
}
Bring tBS0017 back into memory with ToList()
var results = tBS0017.ToList()
.Select(x => convertToRegisto(x));
However, this has some serious flaws.
For every element in tBS0017, you are doing 2 more db query's. You should really be doing this in the one query and projecting to Registo
The issue is that using Linq to Entities tries to convert your C# code into equivalent SQL which can run your query. There is no function "convertToRegisto" in SQL so this gives you an exception.
You can solve the issue by using ToList() to bring the result of the query into memory first. Then you're able to use your methods in the Select.
var teste = tBS0017
.ToList()
.Select(x => convertToRegisto(x));
You can not convert int value from linq to sql. You must use the sql function that convert int to string values. On the other hand, in memory handling is quite heavy operation
e.g
string term = db.ba_terminal.Where(y => "00"+
SqlFunctions.StringConvert((double)y.terminal_id) ==
x.CodTerminal).Select(y => y.terminal_name).ToString();

Appending to the Select part of a query

We have a duplicate part of our LINQ METHOD syntax query. Here is a contrived example.
IQueryable<orders> query = _context.Set<orders>();
var result = query.Select(p => new{
REMAINING = p.qtyOrdered + p.alreadysent,
AWATING = p.qtyOrdered + p.alreadysent
}).ToList();
So we are trying to resolve the duplicate part by putting something in a method and then calling that and getting some sort of result. So something like this....
private IQueryable WhatsLeft()
{
IQueryable<orders> query = _context.Set<orders>();
return query.Select(p => new{p.qtyOrdered + p.alreadysent});
}
IQueryable<orders> query = _context.Set<orders>();
var result = query.Select(p => new{
REMAINING = WhatsLeft(),
AWATING = WhatsLeft()
}).ToList();
Is this at all possible and if so can anyone give me some brief advise on how I would achieve this.
Wouldn't you just simply pass the Order object to the new function directly?
private int Total(Order order)
{
return order.qtyOrdered + order.alreadySent;
}
IQueryable<orders> query = _context.Set<orders>();
var result = query.Select(p => new{
REMAINING = Total(p),
AWATING = Total(p)
}).ToList();
If I understand what you're after correctly. I can't remember off the top of my head how well Linq to sql etc can handle functions, interpreting them into SQL functions. Maybe you could give it a try.
Alternatively, to reduce the complexity of the function (to facilitate L2S conversion) you can make the parameters granular on the function such as:
private int Total(int left, int right)
{
return left + right;
}
Then make the call more like:
var result = query.Select(p => new{
REMAINING = Total(p.qtyOrdered, p.alreadysent),
AWATING = Total(p.qtyOrdered, p.alreadysent)
}).ToList();
UPDATE:
Have you thought about querying the calculation up front?
var result = query.Select(c => c.qtyOrdered + c.alreadysent).Select(p => new {
REMAINING = p,
AWAITING = p
}).ToList();

A lambda expression with a statement body cannot be converted to an expression tree(Lambda and Linq)

Search A lot but did not find any suitable solution for me. I have introduced a variable in lambda expression and that's why showing this error message . Moreover I can solve the problem writing "SQL Like Linq Query" but this is not my expectation..My expectation is to introduce variable in "Linq Using Lambda Expression". Is it Possible or not??
A lambda expression with a statement body cannot be converted to an expression tree.
Here is my code:
IQueryable<IGrouping<int, AnimalFood>> animalFoods = db.AnimalFoods.GroupBy(x => x.FoodId);
IQueryable<FoodSummaryViewModel> foodSummaryViewModel = animalFoods.Select(g =>
{
var animalFood = g.FirstOrDefault();
return new FoodSummaryViewModel()
{
FoodName = animalFood.Food.FoodName,
FoodPrice = animalFood.Food.UnitPrice,
TotalFoodQuantity = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity),
TotalPrice = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity) * animalFood.Food.UnitPrice
};
});
return foodSummaryViewModel.ToList();
The error message is quite clear: you have a lambda expression with a statement body, and that simply cannot be converted to an expression tree (at least not automatically by the compiler). Because of that, your linq provider cannot create a query from it to send to the database (and even if you created the expression tree manually, which is not trivial, your linq provider would not be able to convert it to a SQL query).
You have two options. Option one is to rewrite your query such that it does not contain a statement body, as others have shown.
The other option is to execute part of the query in memory, using linq to objects. You have to be careful with this approach, and avoid getting too much data from the database. But the way to do it would be:
IEnumerable<IGrouping<int, AnimalFood>> animalFoods =
db.AnimalFoods.GroupBy(x => x.FoodId).AsEnumerable();
IEnumerable<FoodSummaryViewModel> foodSummaryViewModel = animalFoods.Select(g =>
{
var animalFood = g.FirstOrDefault();
return new FoodSummaryViewModel()
{
FoodName = animalFood.Food.FoodName,
FoodPrice = animalFood.Food.UnitPrice,
TotalFoodQuantity = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity),
TotalPrice = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity) * animalFood.Food.UnitPrice
};
});
return foodSummaryViewModel.ToList();
That may give you what you think you want, but it may not be a good idea though. Your selector is using the AnimalFood.Animal.AnimalQuatity property chain, and that may cause lazy loading, depending on your Linq provider. And if you have configured it to use eager loading, you may not be better of, because you may be loading way too much data.
So you probably would be better of rewriting your query. Are you sure something like this doesn't do the job:
var q = from food in db.Foods
select new FoodSummaryViewModel
{
FoodName = food.FoodName,
FoodPrice = food.UnitPrice,
TotalFoodQuantity = (from fa in food.AnimalFoods
select fa.Animal.AnimalQuantity).Sum() * food.FoodQuantity
TotalPrice = (from fa in food.AnimalFoods
select fa.Animal.AnimalQuantity).Sum() * food.FoodQuantity * food.UnitPrice
};
return q.ToList();
You can't write a multi-line method inside a linq-2-db query, because this multi-line method can't be transformed into an expression tree than can interpreted by the provider and thus converted into pure SQL statement. You can do this:
var results = (from f in animalFoods
group f by f.FoodId into groups
let animalFood = groups.First()
select new FoodSummaryViewModel()
{
FoodName = animalFood.Food.FoodName,
FoodPrice = animalFood.Food.UnitPrice,
TotalFoodQuantity = groups.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity),
TotalPrice = groups.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity) * animalFood.Food.UnitPrice
}).ToList();

LINQ to Entities create dynamic field

I am trying to create a dynamic field using LINQ to Entities w/ EF5. Based on certain conditions (which I've encapsulated in a function) the dynamic field will be populated with different values.
I referenced the post here but when I run the code below, I get the follow error:
LINQ to Entities does not recognize the method 'System.String FormatName()' method, and this method cannot be translated into a store expression.
public static IEnumerable<dynamic> SelectAllCustomers()
{
using (var db = new DatabaseContext())
{
var query = db.Customer.Select(c => new
{
c.ID,
FullNameLastFirstMiddle = FormatName(c.First_Name, c.Middle_Name, c.Last_Name),
}
);
return query.ToList();
}
}
private static string FormatName(string first, string middle, string last)
{
//format name
if (!String.IsNullOrWhiteSpace(first))
{
if (!String.IsNullOrWhiteSpace(middle))
return last + ", " + first + " " + middle;
else
return last + ", " + first;
}
else
{
if (!String.IsNullOrWhiteSpace(middle))
return last + ", " + middle;
else
return last;
}
}
Any ideas on how best to dynamically build a field with sofisticated logic using LINQ to Entities?
String formatting like that doesn't really need to be translated to SQL and performed on the database side in the first place. Instead just query the database for the information that you need and then perform the string manipulation on the application side using LINQ to objects:
var query = db.Customer.Select(c => new
{
c.ID,
c.First_Name,
c.Middle_Name,
c.Last_Name,
})
.AsEnumerable()
.Select(c => new
{
c.ID,
FullNameLastFirstMiddle =
FormatName(c.First_Name, c.Middle_Name, c.Last_Name),
});

Categories

Resources