I have a lambda expression that returns the sum of two fields in a table. The problem is that the field (ExpectedQuantity) is a string, while QtyExpected is an int. I thought I would be able to use int.Parse in my lambda expression, but I get an error saying that SQL cannot translate it.
return new QuantitiesDashboardAggregate()
{
QtyExpected = query.Sum(x => int.Parse(x.ExpectedQuantity)),
QtyReceived = query.Sum(x => int.Parse(x.ReceivedQuantity)),
};
Can someone help?
Here is how I defined the query variable:
IQueryable<Data.POProduct> query = this.Database.POProducts;
// Apply date range
DateRange dateRange = new DateRange(args.DateRangeFilter, args.DateRangeCriteria);
switch (dateRange.DateRangeFilter)
{
case DateRangeFilter.Date:
query = query.Where(po => po.PurchaseOrder.FiscalDate.Date == dateRange.Date);
break;
case DateRangeFilter.FiscalWeek:
query = query.Where(po => (po.PurchaseOrder.FiscalDate.Year == dateRange.Year) &&
(po.PurchaseOrder.FiscalDate.WeekYear == dateRange.Number));
break;
case DateRangeFilter.FiscalPeriod:
query = query.Where(po => (po.PurchaseOrder.FiscalDate.Year == dateRange.Year) &&
(po.PurchaseOrder.FiscalDate.Period == dateRange.Number));
break;
case DateRangeFilter.FiscalYear:
query = query.Where(po => po.PurchaseOrder.FiscalDate.Year == dateRange.Year);
break;
default:
break;
}
Basically Linq to SQL cannot translate your expression, so you should call .ToList() (or .AsEnumerable()) on your query, it will fetch data drom db, and than you can use your expression with int.Parse
Related
I am using JPA Specification Queries where we follow the common Architecture as below for the Queries
#Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
// Create a new predicate list
List<Predicate> predicates = new ArrayList<>();
// Add criteria to predicates
for (SearchCriteria criteria : list) {
switch (criteria.getOperation()) {
case EQUAL:
predicates.add((Objects.isNull(criteria.getJoinMap()) || criteria.getJoinMap().isEmpty())
? builder.equal(root.get(criteria.getKey()), criteria.getValue())
: builder.equal(getOrCreateJoins(root, criteria.getJoinMap()).get(criteria.getKey()),
criteria.getValue()));
break;
case MATCH:
predicates.add((Objects.isNull(criteria.getJoinMap()) || criteria.getJoinMap().isEmpty())
? builder.like(builder.lower(root.get(criteria.getKey())),
"%" + criteria.getValue().toString().toLowerCase() + "%")
: builder.like(
builder.lower(getOrCreateJoins(root, criteria.getJoinMap()).get(criteria.getKey())),
"%" + criteria.getValue().toString().toLowerCase() + "%"));
break;
case SORT_ASC:
query.orderBy((Objects.isNull(criteria.getJoinMap()) || criteria.getJoinMap().isEmpty())
? builder.asc(root.get(criteria.getKey()))
: builder.asc(getOrCreateJoins(root, criteria.getJoinMap()).get(criteria.getKey())));
break;
case SORT_DESC:
query.orderBy((Objects.isNull(criteria.getJoinMap()) || criteria.getJoinMap().isEmpty())
? builder.desc(root.get(criteria.getKey()))
: builder.desc(getOrCreateJoins(root, criteria.getJoinMap()).get(criteria.getKey())));
default:
break;
}
}
return isSearchOperationOr ? builder.or(predicates.toArray(new Predicate[0]))
: builder.and(predicates.toArray(new Predicate[0]));
}
In this we have key and value/values which are being processed but I want the order of Ids which I provide in IN Query to be same in order while the results are being fetched.
Already gone through the FIND_IN_SET term as from mysql it is possible but any idea how to configure here in the above code?
I've been working on a project that stores case classes in a database and can take them back out again, storing them works fine but I am having trouble with getting them back out.
For items like Strings, Ints, Floats, etc, are being stored as they are but other types are converted to a JSON string using json4s like so
private def convertToString(obj: AnyRef, objType: Class[_]): String = {
implicit val formats = Serialization.formats(NoTypeHints)
objType match {
case t if t == classOf[String] => obj.asInstanceOf[String]
case t if t == classOf[Int] => obj.toString
case t if t == classOf[Integer] => obj.toString
case t if t == classOf[Boolean] => if (obj.asInstanceOf[Boolean]) "true" else "false"
case t if t == classOf[Short] => obj.toString
case t if t == classOf[Double] => obj.toString
case t if t == classOf[Long] => obj.toString
case t if t == classOf[Float] => obj.toString
case t if t == classOf[Byte] => obj.toString
case _ => write(obj)(formats)
}
}
This is working fine and store items just like I would expect it to, but the problem is converting the items back from JSON.
Lets say I have the case class Test(testInt: Int, testString: String, testMap: Map[String, _]) and I get the data back as 3,'blablabla','{"Test": "Map"}'
I can put all values into a new instance of the class expect for the map, here is the code I am using
private def restoreTypes(objClass: Class[_], argList: Array[Object]): Array[_ <: Object] = {
var correctTypes = Array.empty[Object]
val fields = objClass.getDeclaredFields
for(i <- 0 until fields.length) {
val giveType = argList(i).getClass
val wantedType = fields(i).getType
if(giveType != wantedType && giveType == classOf[String])
read[/*HERE*/](argList(i).asInstanceOf[String])
else
correctTypes = correctTypes :+ argList(i)
}
correctTypes
}
And this method is called list so
objClass.getConstructors()(0).newInstance(restoreTypes(objClass, args): _*)
I am getting stuck on how to pass the wanted type to the read method
I'm trying to create linq lambda expression to return customer whose first or last name starts with specific letters. However i get the error on .select saying that:
operator '.' cannot be applied to lambda expression.
public JsonResult GetCust(string term)
{
var data = context.Customers
.Where((dr => dr.First.StartsWith(term) == true) || (dr => dr.Last.StartsWith(term) == true))
.Select(dr => new { Name=String.Concat(dr.First, dr.Last), Adrs = dr.Street, value = dr.CustID })
.Take(10);
return Json(data, JsonRequestBehavior.AllowGet);
}
Any idea how can I return needed data?
In the following line:
.Where((dr => dr.First.StartsWith(term) == true) || (dr => dr.Last.StartsWith(term) == true))
you are using the ||-Operator on two lambda-expressions.
The Where-Clause should more look like this:
.Where(dr => dr.First.StartsWith(term) || dr.Last.StartsWith(term))
I have Linq to SQL query which return one field with Url and I bind it to asp.net combobox. I need to add new virtual record("All Url") to Linq to SQL result before binding the result. How to do that?
var results =
dataAccess.Statistics.
Where(s => s.DateStamp >= minDate && s.DateStamp <= DateTime.UtcNow && s.UserId == userId).
GroupBy(s => s.Url).
Where(g => g.Count() > 1).
OrderBy(g => g.Count()).
Select(g => new { Url = dataAccess.getDomain(g.Key) });
ddlDomain.DataSource = results;
ddlDomain.DataBind();
Add an item to the combobox, then append the databound items:
ddlDomain.Items.Add(new ListItem() { Text = "All Url" });
ddlDomain.AppendDataBoundItems = true;
ddlDomain.DataSource = results;
ddlDomain.DataBind();
I have a linq query that needs to pull a date column out of a row. The expression currently looks like this
myObject.OrderByDescending(s=> s.MyDate).Where(s => s.CRAStatus.Description == "CheckedOut").FirstOrDefault().MyDate)
The problem is that if there are no rows that are "CheckedOut", the query will return a null and attempting to get "MyDate" will throw an exception. We have some verbose solutions, like:
.ForMember(dest => dest.CheckOutDate, opt => opt.MapFrom(src => {
var temp = src.CRAStatusChangeEvents.OrderByDescending(s=> s.MyDate).Where(s => s.CRAStatus.Description == "CheckedOut").FirstOrDefault();
return temp == null ? temp.MyDate : null;
}));
But it would be nice to find something a little more concise. Any Ideas?
Why not
myObject.OrderByDescending(s=> s.MyDate)
.Where(s => s.CRAStatus.Description == "CheckedOut")
.Select(s => s.MyDate as DateTime?)
.FirstOrDefault();
or
myObject.Where(s => s.CRAStatus.Description == "CheckedOut")
.Max(s => s.MyDate as DateTime?);
One option is to set the default if empty to an "empty" instance (think of string.Empty--its a known instance that represents an empty result):
var date = (myObject
.OrderByDescending(s=> s.MyDate)
.Where(s => s.CRAStatus.Description == "CheckedOut")
.DefaultIfEmpty(MyObject.Empty)
.FirstOrDefault()).MyDate;
Here's a snippet that shows how it works:
var strings = new string[]{"one", "two"};
var length =
(strings.Where(s=>s.Length > 5)
.DefaultIfEmpty(string.Empty)
.FirstOrDefault()).Length;
run that and length is 0. Remove the DefaultIfEmpty line and you get a NRE.
var checkedOut = myObject.Where(s => s.CRAStatus.Description == "CheckedOut");
if (checkedOut.Count() > 0) {
var result = checkedOut.Max(s=> s.MyDate).MyDate;
}
How about an extension method?
static class MyObjectEnumerableExtensions
{
public static TMember GetMemberOfFirstOrDefault<TMember>(this IEnumerable<MyObject> items, Func<MyObject, TMember> getMember)
{
MyObject first = items.FirstOrDefault();
if (first != null)
{
return getMember(first);
}
else
{
return default(TMember);
}
}
}
Sample usage:
List<MyObject> objects = new List<MyObject>();
objects.Add(new MyObject { MyDate = DateTime.MinValue });
var filteredObjects = from s in objects where s.MyDate > DateTime.MinValue select s;
DateTime date = filteredObjects.GetMemberOfFirstOrDefault(s => s.MyDate);
Console.WriteLine(date);