EF6 generating date comparison sql for MySql database - mysql

I have a web app built in .NETCore 2.1 which calls an API built in .Net 4.6. The API calls a services layer which is using entity framework 6. I'm connecting to a MySql database. I'm using the Pomelo.EntityFrameworkCore.MySql connector. When using a LINQ query to get records based on a date comparison, EF6 appears to be cmparing the dates as string literals.
I've tried all different types of variations of the LINQ query and looked online for extension libraries that do date comparisons, but to no avail
Here's the LINQ query
int year = DateTime.Now.Year;
DateTime firstDayOfYear = new DateTime(year, 1, 1);
DateTime lastDayOfYear = new DateTime(year, 12, 31);
var startDate = firstDayOfYear.AddYears(-2);
var endDate = lastDayOfYear.AddYears(-1);
var company = dbContext.Companies.Where(c =>
c.Updating &&
c.UpdatedBy == username &&
c.LastUpdate > startDate &&
c.LastUpdate < endDate)
.FirstOrDefault();
Here's part of the SQL that is generated. note the # symbols before the date values
`Extent2`.`ID` AS `ID1`,
`Extent2`.`Name` AS `Name1`
FROM Company AS `Extent1` INNER JOIN `Table_2` AS `Extent2` ON `Extent1`.`ID` = `Extent2`.`ID`
WHERE ((((`Extent1`.`SomeFlag` != 1) AND (`Extent1`.`LastUpdate` > #'01/01/2017 00:00:00')) AND (`Extent1`.`LastUpdate` < #'31/12/2017 00:00:00')) AND ((`Extent1`.`ID` IN ( '1','2','6','7','8' )) AND (`Extent1`.`ID` IS NOT NULL))) AND (NOT ((`Extent1`.`Telephone` IS NULL) OR ((LENGTH(`Extent1`.`Telephone`)) = 0)))) AS `Project1`
Running the sql query manually in MySql workbench returns no rows. if I remove the # symbols it does return rows, as expected. What am I doing wrong?

I couldn't figure out why EF was translating the LINQ that way so I just used a stored procedure call to get round it. At least then I could write the SQL myself.
int year = DateTime.Now.Year;
DateTime firstDayOfYear = new DateTime(year, 1, 1);
DateTime lastDayOfYear = new DateTime(year, 12, 31);
var startDate = firstDayOfYear.AddYears(QueueConfig.UpdateQueueStartDateInYears);
var endDate = lastDayOfYear.AddYears(QueueConfig.UpdateQueueStartDateInYears);
var userParam = new MySql.Data.MySqlClient.MySqlParameter("userName", username);
var sdParam = new MySql.Data.MySqlClient.MySqlParameter("startDate", startDate);
var edParam = new MySql.Data.MySqlClient.MySqlParameter("endDate", endDate);
var lockedCompany = dbContext.Database.SqlQuery<CompanyDto>("CALL GetLockedCompany(#userName,#startDate,#endDate)", userParam, sdParam, edParam);
var companyDto = lockedCompany.SingleOrDefault();

Related

Converting DateandTime to time and comparing with DB for validation

I want to write a validation in such a way that my query should result true if same CCN and date already exist in DB, from JSON and IN DB datetime is saved in "yyyy-MM-dd HH:mm:ss", but in my validation i need to take only date[yyyy-MM-dd] and compare.
I am new to spring boot
This is what i have in my model class
#JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
#Temporal(TemporalType.DATE)
private Date datetime;
Repository for my class
#Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM TABLEX c WHERE c.ccn = :ccn and c.datetime= :datetime")
boolean isExistbyCcnAndDate(#Param("ccn") String conveyancereferencenumber, #Param("datetime") #DateTimeFormat(pattern = "yyyy-MM-dd") Date date);
When i try this it gives result as always false.
This is how i am passing values to repository
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateString = sdf.format(model.getDatetime());
convertedDate = sdf.parse(dateString);
isExistCcnAndDate=repository.isExistbyCcnAndDate(model.getCcn(),convertedDate);
Check out my sqlfiddle.
http://sqlfiddle.com/#!9/5305eb/3
Using sql fiddle this will work:
Create shema:
create table c(datetime DATETIME, ccn TEXT)
insert into c (datetime, ccn) values ('2020-01-01 10:10:50' , 'a');
Try to read and filter step by step:
select * from c;
select * from c where c.datetime = '2020-01-01 10:10:50';
select * from c where date(c.datetime)= date('2020-01-01');
As I already said, whether you can use date(), DATE() or whatever depends on your server, sqlfiddle is MySQL.

MySQL using BETWEEN not returning anything?

I am trying to get all rows from my MySQL database that are from the last week and also have the right company_id. I don't understand why this isn't returning any data, as there are no errors.
A screenshot of the database:
My code:
// Create Calendar and Date objects
Calendar calendar = Calendar.getInstance();
java.sql.Date date = new java.sql.Date(calendar.getTime().getTime());
// Get all datapoints from last week from this company's id
query = "SELECT * FROM survey_data WHERE (company_id = ?) AND (date_entered BETWEEN ? + interval ? day AND ? + interval ? day)";
preparedStatement = conn.prepareStatement(query);
preparedStatement.setString(1, companyId);
preparedStatement.setDate(2, date);
preparedStatement.setInt(3, -Calendar.DAY_OF_WEEK - 6);
preparedStatement.setDate(4, date);
preparedStatement.setInt(5, -Calendar.DAY_OF_WEEK);
resultSet = preparedStatement.executeQuery();

Sql to Slick Conversion

I am converting SQL queries to slick DSL. I am stuck in timestamp conversion.
My SQL query is:
Select isActive from users where create_time <= TIMESTAMPADD(MINUTE,
${AUTO_EXPIRY_DB_DAYS * HOURS_24 * MINUTES_60}, sysdate())
and isVerified=false;
How to write a slick query for the same?
userQuery.filter(user => user.isVerified === FALSE && user.createdDate
<= ?????).map(_.isActive)
Take a look at scalar database functions slick documentation. I suppose this should work:
val sysdate = SimpleLiteral[java.sql.Timestamp]("sysdate")
val timestampAdd = SimpleFunction.ternary[String, Int, java.sql.Timestamp, java.sql.Timestamp]("TIMESTAMPADD")
userQuery
.filter(user => user.isVerified === FALSE
&& user.createdDate <= timestampAdd("MINUTE", 20, sysdate))
.map(_.isActive)

Creating LINQ to SQL for counting a parameter

I'm trying to translate a sql query into LINQ to SQL. I keep getting an error "sequence operators not supported for type 'system.string'" If I take out the distinct count part, it works. Is it not because I'm using the GROUP BY?
SELECT COUNT(EpaValue) AS [Leak Count], Location, EpaValue AS [Leak Desc.]
FROM ChartMes.dbo.RecourceActualEPA_Report
WHERE (EpaName = N'LEAK1') AND (Timestamp) > '20100429030000'
GROUP BY EpaValue, Location
ORDER BY Location, [Leak Count] DESC
Dim temp = (From p In db2.RecourceActualEPA_Reports _
Where (p.Timestamp >= str1stShiftStart) And (p.Timestamp < str2ndShiftCutoff) _
And (p.EpaName = "Leak1") _
Select p.EpaName.Distinct.Count(), p.Location, p.EpaValue)
p.EpaName seems to be a string, not a collection so you can't apply Count() there.
Here is the query you're trying to build (according to your SQL query) using LINQ (I'm not familiar with VB, so the query is written in C#):
var temp =
db2.RecourceActualEPA_Reports
.Where(p =>
p.Timestamp >= str1stShiftStart &&
p.Timestamp < str2ndShiftCutoff &&
p.EpaName == "Leak1"
).GroupBy(p => new { Key1 = p.EpaValue, Key2 = p.Location })
.Select(g => new
{
Count = g.Count(),
Value = g.Key.Key1,
Location = g.Key.Key2
}).OrderBy(i => new { i.Location, i.Count });
And please, in the future format and highlight your code using this, not (or not only) using VS/Management Studio.
Here is how it is formatted in SQL and in Visual Studio
SQL
SELECT COUNT(EpaValue) AS [Leak Count], Location, EpaValue AS [Leak Desc.]
FROM ChartMes.dbo.RecourceActualEPA_Report
WHERE (EpaName = N'LEAK1') AND (Timestamp) > '20100429030000'
GROUP BY EpaValue, Location
ORDER BY Location, [Leak Count] DESC
VB
Dim temp = (From p In db2.RecourceActualEPA_Reports _
Where (p.Timestamp >= str1stShiftStart) And (p.Timestamp < str2ndShiftCutoff) _
And (p.EpaName = "Leak1") _
Select p.EpaName.Distinct.Count(), p.Location, p.EpaValue)

Beginner LINQ syntax question

I have a basic SQL Table ( pKey INT, TransDate smallDateTime, Amount Float)
I simply want to emulate this SQL in LINQ
SELECT SUM(Amount) AS result
FROM dbo.Basic
WHERE TransDate >= #startDate
AND TransDate <= #EndDate
I have created the LINQ dbml for this and I can get basic query results for a date range
However I can't find the right syntax to get the SUM over a dateRange, I've tried several variations on the following but either they dont compile, or the result they give cannot be converted to a double
BasicDataContext dContext = new BasicDataContext();
var lnq = from c in dContext.Basic
where c.TransDate >= startdate &&
c.TransDate <= enddate
select new { total = c.Sum(Amount) };
double result = (double)lnq.total;
This should work:
double result = (from c in dContext.Basic
where c.TransDate >= startdate &&
c.TransDate <= enddate
select c.Amount).Sum();