How to convert sql sum with case to linq - linq

SUM(CASE WHEN [dbo].[tblHits].IsLike = 1 THEN 1 ELSE 0 END) as Likes
i want some thing like this ,below code is giving me error
cannot implicitly convert type bool? to decimal?
TotalLikes = grouped.Sum(d => d.IsLike == true ? d.IsLike = true : d.IsLike = false )

The most direct translation would be:
TotalLikes = grouped.Sum(d => d.IsLike == true ? 1 : 0)
which can be shortened to:
TotalLikes = grouped.Sum(d => d.IsLike ? 1 : 0)
but I would use:
TotalLikes = grouped.Count(d=>d.IsLike);

Related

SQLAlchemy custom boolean

I have an Oracle database with boolean logic implemented this way:
MYCOL NUMBER(1,0)
0 = False
-1 or 1 = True
NULL = None
With a default SQLAlchemy boolean column, -1 table value doesn't match False or True.
Is it possible to create an SQLAlchemy custom type that maps such a column to a bool python attribute?
The difficulty relies in having multiple values associated with true.
Ex:
session.query(User).filter_by(active=True)
Should generate one of these queries:
select * from user where active != 0;
select * from user where active in (-1, 1);
select * from user where 1 = (CASE WHEN active != 0 THEN 1 ELSE active end);
This implementation seems to work for basic queries.
Case when expression seems to be the easiest solution because operator logic isn't altered.
class CustomBoolean(sqlalchemy.types.TypeDecorator):
"""0 = False
-1 or 1 = True
NULL = None
By default, SQLAlchemy only supports 0 and 1"""
impl = Boolean
cache_ok = True
# In select or group by clause, replace col with expression: (CASE WHEN col != 0 THEN 1 ELSE col end)
def column_expression(self, col):
expr = col.expr
if isinstance(expr.type, CustomBoolean):
res = sqlalchemy.case(
(type_coerce(expr, Integer()) != sqlalchemy.literal_column("0", type_=Integer), sqlalchemy.literal_column("1", type_=Integer)),
else_=type_coerce(expr, Integer())
)
return type_coerce(res, Boolean())
expr.type = Boolean()
return expr
# In where clause, replace col with expression: (CASE WHEN col != 0 THEN 1 ELSE col end)
class comparator_factory(Boolean.Comparator):
def operate(self, op, other, **kwargs):
op1 = self
if hasattr(op1, "__clause_element__"):
clause = op1.__clause_element__()
if isinstance(clause.type, CustomBoolean):
op1 = self.normalise(clause)
op2 = other
if hasattr(op2, "__clause_element__"):
clause = op2.__clause_element__()
if isinstance(clause.type, CustomBoolean):
op2 = self.normalise(clause)
return op(
op1, op2, **kwargs
)
#staticmethod
def normalise(expr):
res = sqlalchemy.case(
(type_coerce(expr, Integer()) != sqlalchemy.literal_column("0", type_=Integer), sqlalchemy.literal_column("1", type_=Integer)),
else_=type_coerce(expr, Integer())
)
return type_coerce(res, Boolean())

Having trouble trying to order using linq

I am trying to order by start date(s.StartDate). Below is my code so far, my understanding is that I should be adding .orderby(s.StartDate) somewhere but I don't think I'm even taking the correct route now as I have tried many ways.
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
select s;
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
if (startDate != null)
{
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
}
You should be able to start with the "without startdate" option - you have a couple of options here - either declare the type of the query specifically:
IQueryable<SessionSearch> query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
order by s.StartDate
select s;
And then as you've tried, add the additional where clause to the query if there's a start date passed in:
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
This means that you would not be able to add further ordering via the ThenBy methods.
Alternatively, you can add the order by clause after you've finished adding the where clauses:
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
select s;
if (startDate != null) {
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
}
query = query.OrderBy(s => s.StartDate);
Props to JonSkeet for pointing these out.

Dynamic field type?

I have the following code:
queryProjects = queryProjects
.Where(a => a.Field<int>("ProjectType") == projectType
&& a.Field<string>("Descr")
.IndexOf(#str, StringComparison.OrdinalIgnoreCase) >= 0
|| a.Field<string>("ProjectId")
.IndexOf(#str, StringComparison.OrdinalIgnoreCase) >= 0
|| a.Field<string>("LastChangedBy")
.IndexOf(#str, StringComparison.OrdinalIgnoreCase) >= 0
);
How can I make the a.Field< ??? > the data type dynamic where the question marks are?
On the type where your field property is, redefine it like so:
public T Field<T>(string key)
{
object field = null; // Get your field value here
return (T)field;
}

Needing a DataSet to be captured into a Linq Lambda expression

I was using a List / IEnumerable but need to instead populate properties from a class called ChildInfo I cannot seem to get the data from the dataset into my ChildInfo class of properties , thanks in advance for insight on this.
public ChildInfo GetScreenData(string pCert, string pScreen)
{
DataSet dataSet = _WCFClient.Get_Screen_Data(pCert, pScreen);
ChildInfo childinfo = (from c in dataSet.Tables[0]
select new ChildInfo()
{
FirstName = c[0] == DBNull.Value ? "" : c[0].ToString(),
MiddleName = c[1] == DBNull.Value ? "" : c[1].ToString(),
LastName = c[2] == DBNull.Value ? "" : c[2].ToString(),
Suffix = c[3] == DBNull.Value ? "" : c[3].ToString(),
ChildNotNamed = c[4] == DBNull.Value ? false : (bool)c[4],
Sex = c[5] == DBNull.Value ? "" : c[5].ToString(),
DOB = c[6] == DBNull.Value ? "" : c[6].ToString(),
Hour = c[7] == DBNull.Value ? "" : c[7].ToString(),
Minute = c[7] == DBNull.Value ? "" : c[7].ToString(),
CountryBirth = c[9] == DBNull.Value ? "" : c[9].ToString(),
CityBirth = c[10] == DBNull.Value ? "" : c[10].ToString()
});
return childinfo;
}

help with linq query

i am trying to get some data, but i dont know how can i do a if in linq, this is how i am trying to do
from so in db.Operations
where ((opType!= "0" ? so.Operation == int.Parse(opType) : false)
&& (idState!=0 ? so.State == idState : false)
&& (start != null ? so.StartDate == start : false)
&& (end !=null ? so.EndDate == end : false))
select so
the optype is a Int,
the idState is a Int,
end is a datetime,
start is a datime
what i am trying to do is, if those aren't null they add to the query function, so i can get all data together
for example: in c# code
if((opType!= "0")
where (so.Operation == int.Parse(opType)
if(idState!=0)
where (so.Operation == int.Parse(opType) && so.State == idState
.......
so if that isn't null, that sentence in that sql query (the TRUE part, i dont want to use the false part), add it to the where, so i can search all parameters that aren't null or 0
Since you're &&'ing them, looks like you want : true instead of : false.
Well not sure what you want exactly but here is a try:
var query = db.Operations.AsQueryable();
if (opType != null && opType != "0")
query = query.Where(x => x.Operation == int.Parse(opType);
if (idState != 0)
query = query.Where(x => x.State == idState);
if (start != null) // assuming that start is of type DateTime? otherwise use DateTime.MinValue
query = query.Where(x => x.StartDate.Date == start); // maybe >= is more appropriate
if (end != null) // also DateTime? assumed
query = query.Where(x => x.EndDate.Date == end); // maybe <= is more appropriate
var result = query.ToList(); // e.g. could also do an foreach, depending what you want to do
The trick in this approach is to build up the query successively. The query will not be enumerated until .ToList() or foreach is used to enumerate the list.
Actually this should yield the same:
from so in db.Operations
where ((opType != null && opType!= "0" ? so.Operation == int.Parse(opType) : true)
&& (idState!=0 ? so.State == idState : true)
&& (start != null ? so.StartDate.Date == start : true)
&& (end !=null ? so.EndDate.Date == end : true))
select so
opType!= "0" ? so.Operation == int.Parse(opType) : false
you should not use so.operation == int.parse.... instead use so.operation = int.Parse(opType)
You can use conditional parameters.
Change:
where ((opType!= "0" ? so.Operation == int.Parse(opType) : false)
To:
where ((opType!= "0" ? so.Operation == int.Parse(opType) : so.Operation == Operation)
and so on...

Resources