Here what I would like to do:
var groups =
from g in Group.All()
where g.FirstDay < startDate && (g.LastDay == null || g.LastDay >= startDate)
select g;
FirstDate is a dateTime and LastDate is a nullable datetime. I'm getting an "System.InvalidOperationException: The operators of the 'LessThan' do not correspond with parameters from the method 'op_LessThan'."
This query works with small modifications (and completely different results!) like:
var groups =
from g in Group.All()
where g.LastDay == null && g.FirstDay < startDate
select g;
var groups =
from g in Group.All()
where (g.LastDay >= startDate || g.LastDay == null)
select g;
I already changed the order of the expressions, but it do not change the results...
Any ideas?!
Thanks!!! I am getting crazy with this small query!
Related
I am trying to create a function which counts and sums values by day (to later calculate the average). I got this far:
CREATE OR REPLACE FUNCTION state_group_count_and_sum( state map<timestamp, frozen<tuple<bigint,double>>>, timestamp timestamp, value double )
CALLED ON NULL INPUT
RETURNS map<timestamp, frozen<tuple<bigint,double>>>
LANGUAGE java AS '
Date date = (Date) timestamp;
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();
TupleValue tupleValue = state.get(date);
Long count = (Long) tupleValue.getLong(0);
if (count == null) count = 1L;
else count = count + 1L;
Double sum = (Double) tupleValue.getDouble(1);
if (sum == null) sum = value;
else sum = sum + value;
//if (tupleValue == null) ?
tupleValue.setLong(0, count);
tupleValue.setDouble(1, sum);
state.put(date, tupleValue);
return state; ' ;
CREATE OR REPLACE AGGREGATE group_count_and_sum(timestamp, double)
SFUNC state_group_count_and_sum
STYPE map<timestamp, frozen<tuple<bigint,double>>>
INITCOND {};
This fails because tupleValue is null at every new day which is not in the map yet. How do I instantiate a tuple value in a UDA?
Fixed it.
CREATE OR REPLACE FUNCTION state_group_count_and_sum( state map<timestamp, frozen<tuple<bigint,double>>>, timestamp timestamp, value double )
CALLED ON NULL INPUT
RETURNS map<timestamp, frozen<tuple<bigint,double>>>
LANGUAGE java AS '
Date date = (Date) timestamp;
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();
TupleValue tupleValue = state.get(date);
if (tupleValue == null) {
com.datastax.driver.core.TupleType tupleType = com.datastax.driver.core.TupleType.of(com.datastax.driver.core.ProtocolVersion.NEWEST_SUPPORTED, com.datastax.driver.core.CodecRegistry.DEFAULT_INSTANCE, com.datastax.driver.core.DataType.bigint(), com.datastax.driver.core.DataType.cdouble());
tupleValue = tupleType.newValue(0L, 0.0);
}
Long count = (Long) tupleValue.getLong(0);
if (count == null) count = 1L;
else count = count + 1L;
Double sum = (Double) tupleValue.getDouble(1);
if (sum == null) sum = value;
else sum = sum + value;
tupleValue.setLong(0, count);
tupleValue.setDouble(1, sum);
state.put(date, tupleValue);
return state; ' ;
CREATE OR REPLACE AGGREGATE group_count_and_sum(timestamp, double)
SFUNC state_group_count_and_sum
STYPE map<timestamp, frozen<tuple<bigint,double>>>
INITCOND {};
I'm trying to assign a percentage of a number to it's number limit it worked as an If/Else statement but when I tried to convert it to a boolean Switch I get a "not a statement" error
I cant tell what it is that I'm doing wrong here.
public static boolean taxRate(double rate)
{
final double LOW_LIM = 15000;
final double LOW_RATE = 0.25;
final double MEDIUM_LIM = 49001;
final double MEDIUM_RATE = 0.5;
final double HIGH_LIM = 49002;
final double HIGH_RATE = 0.75;
boolean taxRate;
switch(taxlimit)
{
case(LOW_LIM):
yearlyIncome <= LOW_LIM;
taxRate = LOW_RATE;
break;
case(MEDIUM_LIM):
yearlyIncome <= yearlyIncome >= MEDIUM_LIM && yearlyIncome < HIGH_LIM;
taxRate = MEDIUM_RATE;
break;
case(HIGH_LIM):
yearlyIncome <= HIGH_LIM;
taxRate = HIGH_RATE;
}
return taxRate();
}
The switch statement only works with constants and only checks for equality. You can replase IF/ELSE with a SWITCH only if your IFs look like this
if (var == const1) .....;
else if (var == const2) ....;
else if (var == const3) ....;
else .....;
This
yearlyIncome <= yearlyIncome >= MEDIUM_LIM && yearlyIncome < HIGH_LIM;
is not a statement, but an expression - it does not say WHAT to do. A statement MUST say what to do.
I have a json which is generated on runtime with x amount of properties and for this reason I can't use a POCO to deserialize it e.g.
"{"UserId": 1234,"Name": "Adnan","Age": 30, "Salary": 3500.65}"
The best option for me is to deserialize it in Dictionary<string,object>
I am using ServiceStack JsonSerializer to deserialize the json to a Dictionary<string,object> which works fine, but when I try to get types of the objects in the dictionary they do not match accordingly.
I have tried the following:
If I don't use the following options all dictionary object values are inferred as strings
JsConfig.ConvertObjectTypesIntoStringDictionary = true;
JsConfig.TryToParsePrimitiveTypeValues = true;
When I use the above options, all Int64 and Double values are inferred as Decimal values.
Is there any option to change this, so that primitive values are inferred as Int64 or Double instead of Decimal
Ps: I have no requirement that it needs to be exact type i.e. Int32 if it falls under that bracket.
I have tried using Json.Net and it works fine and the object values are inferred as Int64 and Double, but as I am using ServiceStack JsonSerializer in my project would be good to know how this can be achieved using that.
Set TryToParseNumericType = true
You need to set JsConfig.TryToParseNumericType = true if you want ServiceStack.Text to determine the type beyond a decimal type.
Controlling the primitive types:
With regard to controlling the types that your numbers are parsed to, I submitted changes to improve ServiceStack.Text, to provide such functionality which will be included in an upcoming release, with this commit.
So you will be able to do:
JsConfig.TryParseNumericType = true;
JsConfig.ParsePrimitiveFloatingPointTypes = ParseAsType.Single;
JsConfig.ParsePrimitiveIntegerTypes = ParseAsType.Int32 | ParseAsType.Int64;
That configuration would return an Int32 instead of a byte, as you indicated was a problem. And instead of decimal you would get a float.
For reference:
Below is the updated primitive parsing method, which should now provide better control, and better fallback options when types cannot be parsed.
public static object ParsePrimitive(string value)
{
if (string.IsNullOrEmpty(value)) return null;
bool boolValue;
if (bool.TryParse(value, out boolValue)) return boolValue;
// Parse as decimal
decimal decimalValue;
var acceptDecimal = JsConfig.ParsePrimitiveFloatingPointTypes.HasFlag(ParseAsType.Decimal);
var hasDecimal = decimal.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out decimalValue);
// Check if the number is an Primitive Integer type given that we have a decimal
if(hasDecimal && decimalValue == decimal.Truncate(decimalValue))
{
// Value is a whole number
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.Byte) && decimalValue <= byte.MaxValue && decimalValue >= byte.MinValue) return (byte)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.SByte) && decimalValue <= sbyte.MaxValue && decimalValue >= sbyte.MinValue) return (sbyte)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.Int16) && decimalValue <= Int16.MaxValue && decimalValue >= Int16.MinValue) return (Int16)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.UInt16) && decimalValue <= UInt16.MaxValue && decimalValue >= UInt16.MinValue) return (UInt16)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.Int32) && decimalValue <= Int32.MaxValue && decimalValue >= Int32.MinValue) return (Int32)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.UInt32) && decimalValue <= UInt32.MaxValue && decimalValue >= UInt32.MinValue) return (UInt32)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.Int64) && decimalValue <= Int64.MaxValue && decimalValue >= Int64.MinValue) return (Int64)decimalValue;
if (JsConfig.ParsePrimitiveIntegerTypes.HasFlag(ParseAsType.UInt64) && decimalValue <= UInt64.MaxValue && decimalValue >= UInt64.MinValue) return (UInt64)decimalValue;
return null;
}
// Value is a floating point number
// Return a decimal if the user accepts a decimal
if(hasDecimal && acceptDecimal)
return decimalValue;
// Parse as double if decimal failed or user wants a double
double doubleValue = 0;
var acceptDouble = JsConfig.ParsePrimitiveFloatingPointTypes.HasFlag(ParseAsType.Double);
var hasDouble = (!hasDecimal || acceptDouble) && double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out doubleValue);
// Return a double if the user accepts a double
if(acceptDouble && hasDouble)
return doubleValue;
// Parse as float
float floatValue;
var acceptFloat = JsConfig.ParsePrimitiveFloatingPointTypes.HasFlag(ParseAsType.Single);
var hasFloat = float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out floatValue);
// Return a float if the user accepts a float
if(acceptFloat && hasFloat)
return floatValue;
// Default to decimal, then double , then float or null
if(hasDecimal) return decimalValue;
if(hasDouble) return doubleValue;
if(hasFloat) return floatValue;
return null;
}
I've a method that returns this exception.
LINQ to Entities does not recognize the method 'System.String stringCutter(System.String)' method, and this method cannot be translated into a store expression.
public List<ProductReqNoDate> GetRequestsQuery()
{
var query = (from r in db.talepler
select new ProductReqNoDate
{
talepEdenBirim = r.talepEdenBirim,
talepNo = r.talepNo,
talepTarihi = r.talepTarihi,
urunAdi = stringCutter((from p in db.urunler
where p.talepNo == r.talepNo
select p.urunAd).FirstOrDefault()) // <--This
}).AsQueryable();
return query.ToList();
}
string stringCutter(string txt)
{
return string.IsNullOrEmpty(txt) ? "" : txt.Length <= 30 ? txt : txt.Substring(0, 30) + "...";
}
when i use this string operations inline, it works. but its too long,
urunAdi = ((from p in db.urunler where p.talepNo == r.talepNo select p.urunAd).FirstOrDefault()).Length <= 30 ?
((from p in db.urunler where p.talepNo == r.talepNo select p.urunAd).FirstOrDefault()) :
((from p in db.urunler where p.talepNo == r.talepNo select p.urunAd).FirstOrDefault()).Substring(0, 30) + "..."
How can i refer (from p in db.urunler where p.talepNo == r.talepNo select p.urunAd).FirstOrDefault()) as txt maybe; so i can use stringCutter method inline like:
urunAdi=string.IsNullOrEmpty(txt) ? "" : txt.Length <= 30 ? txt : txt.Substring(0, 30) + "...";
Is there a way of shortening this code. , thanks
EF is trying to map the function stringCutter into SQL. Which it can't because it does not know about it. The inline version only uses functions that EF knows to map to SQL expressions/function.
IQueryable<> cannot convert your expression to be used with the back-end store. You need to bring a string into memory first, then you can use IEnumerable<>'s projection method to call your method, like this:
return (from r in db.talepler
select new // First, use an anonymous type to read the building blocks
{
r.talepEdenBirim,
r.talepNo,
r.talepTarihi,
urunAdiStr = (from p in db.urunler
where p.talepNo == r.talepNo
select p.urunAd).FirstOrDefault()
}
).AsQueryable()
.ToList() // Force the data into memory
.Select(anon => new ProductReqNoDate {
talepEdenBirim = anon.talepEdenBirim,
talepNo = anon.talepNo,
talepTarihi = anon.talepTarihi,
urunAdi = stringCutter(anon.urunAdiStr) // Now stringCutter is available
}).ToList();
I have 2 tables, Imports and Periods.
Imports has the following structure:
AdminID, PeriodID, Some more fields
1, 1
1, 2
1, 6
1, 50
Periods table has the following structure:
PeriodID, PeriodType, StartDate, EndDate, Description
1, 1, 2007-01-01, 2007-12-31, Year 2007
2, 2, 2007-01-01, 2007-03-31, Quarter 1 2007
3, 2, 2007-04-01, 2007-06-30, Quarter 2 2007
4, 2, 2007-07-01, 2007-09-30, Quarter 3 2007
5, 2, 2007-10-01, 2007-12-31, Quarter 4 2007
6, 3, 2007-01-01, 2007-01-31, January 2007
.
.
.
50, 2, 2011-01-01, 2011-03-31, Quarter 1 2011
Now, I need to build a linq query to fetch only the largest period(ignoring the smaller overlapping periods) based on the data in Imports table!
When I query for AdminID = 1, I should only get PeriodID = 1 & 50, ignoring/excluding the PeriodIDs 2 & 6 as they overlap in 1 and 50 as there is no overlapping data yet!
You, can the max help for picking the largest period and while retrieving the values by comparing the PeriodIDs in both tables right.
I'm not sure whether there is a convenient way to do this in the database, but when you pull the data locally, you can do in-memory LINQ queries, if this is appropriate. You need to do this in thee steps.
Step 1: Define a Range class that allows you to do comparisons on periods (see below).
Step 2: Pulling the periods from the database:
var ranges = (
from period in context.Periods
where period.Imports.Any(i => i.AdminID == adminId)
select new Range(period.StartDate, period.EndDate.AddDays(1)))
.ToArray();
Note the .ToArray() to pull everything locally.
Step 3: Aggregating / merging all the periods into a list of non-overlapping periods:
var mergedPeriods = (
from range in ranges
select ranges.Where(p => p.OverlapsWith(range))
.Aggregate((r1, r2) => r1.Merge(r2)))
.Distinct();
For this to work you need a specially designed Range type that contains OverlapsWith, Merge and Equals methods. It might look like this:
public class Range : IEquatable<Range>
{
public Range(DateTime start, DateTime exclusiveEnd)
{
if (exclusiveEnd < start)
throw new ArgumentException();
this.Start = start; this.End = exclusiveEnd;
}
public DateTime Start { get; private set; }
public DateTime End { get; private set; }
public TimeSpan Duration { get { return this.End - this.Start; } }
public Range Merge(Range other)
{
if (!this.OverlapsWith(other)) throw new ArgumentException();
var start = this.Start < other.Start ? this.Start : other.Start;
var end = this.End > other.End ? this.End : other.End;
return new Range(start, end);
}
public bool Contains(Range other)
{
return this.Start <= other.Start && this.End > other.End;
}
public bool OverlapsWith(Range other)
{
return this.OverlapsOnStartWith(other) ||
other.OverlapsOnStartWith(this) ||
this.Contains(other) ||
other.Contains(this);
}
private bool OverlapsOnStartWith(Range other)
{
return this.Start >= other.Start && this.Start < other.End;
}
public bool Equals(Range other)
{
return this.Start == other.Start && this.End == other.End;
}
}
I hope this helps.
Well, after a long struggle, I did find an answer! With a single query to database!
And for everyone's benefit posting the same.
var oImportPeriods =
from o in Imports
where o.Administration.AdminID == 143
orderby o.Period.PeriodID
select o.Period;
var oIgnorePeriodList = (
from oPeriod in oImportPeriods
from oSearchPeriod in oImportPeriods
.Where(o => o.PeriodID != oPeriod.PeriodID)
where oPeriod.StartDate >= oSearchPeriod.StartDate
where oPeriod.EndDate <= oSearchPeriod.EndDate
select oPeriod.PeriodID)
.Distinct();
var oDeletablePeriods = oAdministrationPeriods
.Where(o => !oIgnorePeriodList.Contains(o.PeriodID));
foreach(var o in oDeletablePeriods)
Console.WriteLine(o.Name);