SQL Server CE and Datetime Select issue (C#) - c#-4.0

I have a select that uses datetime, from two datetimepickers, in the WHERE clause. The SELECT runs fine, populates a datagrid, no problem, but bizzarely the datetime part of the SELECT is completely ignored and the whole thing returns a recordset as if only "WHERE x_account_id = " + subaccountID were employed:
SqlCeConnection conn = new SqlCeConnection(Lib.ConnectionString);
string sql = "SELECT x_scaleid, x_weight, x_timestamp FROM x WHERE x_account_id = " + subaccountID
+ " AND (x_timestamp BETWEEN #start_date AND #end_date) ORDER BY x_timestamp DESC";
SqlCeCommand cmd = new SqlCeCommand(sql, conn);
cmd.Parameters.Add("#start_date", SqlDbType.DateTime, 8).Value = dFromFilter.Value.Date;
cmd.Parameters.Add("#end_date", SqlDbType.DateTime, 8).Value = dToFilter.Value.Date;
SqlCeDataAdapter da = new SqlCeDataAdapter();
da.SelectCommand = cmd;
Not been able to find anyone with the same issue online, so I'm kind of stuck. Maybe I'm better off trying to convert all the datetimes to int's, and store them that way - always hated working with datetime types.
Before anyone asks, I've tried various versions of the clause, including the use of '<' and '>', as well as different CONVERT variations.

I 'solved' the issue, and by 'solved' I mean put in a hack.
I created a new column in the DB, type int, in the x table. As I populate x_timestamp with the current time, derived from the application, I populate this new column with a number constructed out of the date, in the format of 'yyyymmdd'. So when doing any filtering, using dates, I can simply do a numerical comparison using the two dates picked (again converted to similar int formats in the application). Works a treat.
It's not an ideal solution by any stretch, as it duplicates data in the DB, but deadlines are deadlines and if no one else can suggest a better one here, this one may be of help to anyone else with a similar problem in the future.

Related

Getting "Please rebuild this data combination" on a computer but not on another one

This is my first try at using the Power Query... I've build a "dynamic" query in which I can change the retrieved fields as well as the filtering fields and values to be used by the query.
It's working perfectly on my computer but as soon as I try to execute it on another computer, I get the "Please rebuild this data combination" error. I saw some post saying I'll have to kind of split my query but I have not been able to figure it out.
Here is what my 2 tables look like:
Condition and fields selection
and here is my Query with the error:
Query
This might not be very elegant, but it allow me, thru a VBA script, to generate the list of fields to be retrieved and to generate the condition to be used by the SQL.
Any idea why it's not working on the other computers or how to improved the solution I'm using?
Thank you!
Notes:
Hi, all my Privacy Level are already set to 'None'.
I've tried to parametrize my code but I can't figure how. The Where condition is dynamic: it could be Where Number = "1234" but in other condition, the where might be like: 'Where Assignee = "xyz"'.
Here is a simplified example of my code:
let
Source = Sql.Database("xxxx", "yyyy", [Query=
"Select network, testid
from CM3T1M1 "
& paramConditions[Conditions]{0} &
" "])
in
Source
rebuild query, Formula.Firewall
That's a feature to prevent prevent accidentally leaking data. You can change the privacy level to ignore it
See also: docs.microsoft/dataprivacyfirewall
Is the dynamic query inserting those cells into the SQL query ? Report Parameters are nice for letting the user change variables without having to re-edit the query.
Parameterized native SQL queries
from: https://blog.crossjoin.co.uk/2016/12/11/passing-parameters-to-sql-queries-with-value-nativequery-in-power-query-and-power-bi/
let
Source = Sql.Database("localhost", "Adventure Works DW"),
Test = Value.NativeQuery(
Source,
"SELECT * FROM DimDate
WHERE EnglishMonthName=#MonthName AND
EnglishDayNameOfWeek=#DayName",
[
MonthName = "March",
DayName = "Tuesday"
]
)
in
Test
Dynamic Power Query version of SQL Query
To dynamically generate this SQL Query
select NUMBER, REQUESTED_BY from SourceTable
where NUMBER = 404115
Table.SelectRows is your Where.
SelectColumns is your select
let
Source = ...,
filterByNum = 404115,
columnNames = {"NUMBER", "REQUESTED_BY"},
removedColumns = Table.SelectColumns(
Source, columnNames, MissingField.Error
),
// I used 'MissingField.Error' so you know right away
// if there's a typo or bug
// assuming you are comparing Source[NUMBER]
filteredTable = Table.SelectRows(
Source, each [NUMBER] = filterByNum
)
in
filteredTable

How truncate time while querying documents for date comparison in Cosmos Db

I have document contains properties like this
{
"id":"1bd13f8f-b56a-48cb-9b49-7fc4d88beeac",
"name":"Sam",
"createdOnDateTime": "2018-07-23T12:47:42.6407069Z"
}
I want to query a document on basis of createdOnDateTime which is stored as string.
query e.g. -
SELECT * FROM c where c.createdOnDateTime>='2018-07-23' AND c.createdOnDateTime<='2018-07-23'
This will return all documents which are created on that day.
I am providing date value from date selector which gives only date without time so, it gives me problem while comparing date.
Is there any way to remove time from createdOnDateTime property or is there any other way to achieve this?
CosmosDB clients are storing timestamps in ISO8601 format and one of the good reasons to do so is that its lexicographical order matches the flow of time. Meaning - you can sort and compare those strings and get them ordered by time they represent.
So in this case you don't need to remove time components just modify the passed in parameters to get the result you need. If you want all entries from entire date of 2018-07-23 then you can use query:
SELECT * FROM c
WHERE c.createdOnDateTime >= '2018-07-23'
AND c.createdOnDateTime < '2018-07-24'
Please note that this query can use a RANGE index on createdOnDateTime.
Please use User Defined Function to implement your requirement, no need to update createdOnDateTime property.
UDF:
function con(date){
var myDate = new Date(date);
var month = myDate.getMonth()+1;
if(month<10){
month = "0"+month;
}
return myDate.getFullYear()+"-"+month+"-"+myDate.getDate();
}
SQL:
SELECT c.id,c.createdOnDateTime FROM c where udf.con(c.createdOnDateTime)>='2018-07-23' AND udf.con(c.createdOnDateTime)<='2018-07-23'
Output :
Hope it helps you.

"At least one object must implement IComparable" exception from LINQ query results

I have not used LINQ very extensively, but I'm trying to read data from a large Excel spreadsheet (14K+ rows) that requires me to make queries from multiple worksheets and even requery the original spreadsheet to filter specific data. Because OleDb queries of Excel can take a relatively long time (500+ms per query for a file on my local machine), I'm doing a couple of these queries at the front of my method, starting a loop through a "base" DataTable, then trying to use LINQ to filter down the data within that loop to put the appropriate data into a more structured DataSet. Here is some code to help explain (VB.NET):
Dim Connection As System.Data.OleDb.OleDbConnection
Dim Command As System.Data.OleDb.OleDbDataAdapter
Dim EXCEL_SHEET_DATA_1 As New DataTable
Dim EXCEL_SHEET_DATA_2 As New DataTable
Dim EXCEL_SHEET_DATA_3 As New DataTable
Dim TapeFile As New FileInfo("C:\TempFolder\tapefile.xls")
Connection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source='" & TapeFile.FullName & "'; Extended Properties=Excel 8.0;")
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET1$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_1)
Command.Dispose()
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET2$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_2)
Command.Dispose()
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET3$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_3)
Command.Dispose()
For Each Row As DataRow In EXCEL_SHEET_DATA_1.Rows
Dim MemberNumber As String = Row("MEMBER_NUMBER").ToString.Trim
Dim UserNumber As String = Row("USER_ID").ToString.Trim
' -- CODE FOR INITIAL PROCESSING OF SHEET1 DATA - NO ERRORS --
Dim CoMemberQuery As IEnumerable(Of DataRow) = From cm In EXCEL_SHEET_DATA_2 Where cm("MEMBER_NUMBER") = MemberNumber And cm("USER_ID") = UserNumber
For Each CoMemberRow As DataRow In CoMemberQuery
' -- CODE FOR PROCESSING OF SHEET2 DATA - NO ERRORS --
Next CoMemberRow
Dim VehicleQuery As IEnumerable(Of DataRow) = From veh In EXCEL_SHEET_DATA_1 Where veh("MEMBER_NUMBER") = MemberNumber And veh("USER_ID") = UserNumber Order By veh("VIN") Ascending
' *******************************************************
' -->> HERE IS WHERE I *SOMETIMES* GET THE EXCEPTION <<--
' *******************************************************
For Each VehicleRow As DataRow In VehicleQuery
' -- CODE FOR SECONDARY PROCESSING OF SHEET1 DATA - NO ERRORS --
Next VehicleRow
Next Row
I don't get the exception every time. The only thing I've noticed as possibly having something to do with it is that for the specific MemberNumber and UserNumber combination that causes the first exception, the first row in the result set would most likely contain a NULL value for the VIN field.
I'm sure the problem has to do with my LINQ query syntax, but I am simply too inexperienced in this regard to know why it's failing. Any assistance would be greatly appreciated. If you require any additional information regarding the code or implementation, let me know and I'll try to add it to the question.
Thank you for your time.
Your VehicleQuery has the following phrase: Order By veh("VIN") Ascending.
So as soon as VehicleQuery gets evaluated (by starting the For loop), LINQ will evaluate all of the items in that query, and then perform a sorting operation, which involves comparing the veh("VIN") values with each other and putting them in order.
When comparing any two items in your query, it tries to see if either value knows how to compare itself with values of the other type (hence implementing the IComparable interface. If they cannot, then it doesn't know which one should go first.
My guess is that veh("VIN") is (sometimes) yielding objects that don't know how to compare themselves with other values returned by this expression. Depending on the kind of data you're using, and how you want it to be compared, you might consider doing some kind of cast or conversion, or simply calling ToString() on the value, to make sure it's comparable: Order By veh("VIN").ToString() Ascending
(Please pardon any syntax errors, as I'm a C# developer.)

Search query with Subsonic

Ok,
Today I am trying to learn Subsonic. Pretty cool stuff.
I am trying to build some search functionality into my website but am struggling about how I might achieve this in Subsonic.
I have one search field that could contain multiple keywords. I want to return results that match all of the keywords. The target on the search is a single text column.
So far I have this (it runs but never returns results):
return new SubSonic.Select().From(Visit.Schema)
.InnerJoin(InfopathArchive.VisitIdColumn, Visit.VisitIdColumn)
.Where(InfopathArchive.XmlDocColumn).Like(keywords)
.ExecuteTypedList<Visit>();
There is a one to one mapping between the Visit table and the InfoPathArchive table. I just want to return the collection of Visits that have the keywords in the related XMLDocColumn.
If I could get that working it would be great. Now the second problem is that if someone searches for 'australia processmodel' then obviously the above code should only return that exact phrase. How can I create a query that splits up my search term so that it must return documents that contain ALL of the individual search terms?
Any help appreciated.
Edit: Ok, so the basic search works, but the multiple keyword search doesnt. I did what Adam suggested but it seems Subsonic only uses one parameter for the query.
Here is the code:
List<string> wordsInQueryList = keywords.Split(' ').ToList();
SqlQuery q = Select.AllColumnsFrom<Visit>()
.InnerJoin(InfopathArchive.VisitIdColumn, Visit.VisitIdColumn)
.Where(Visit.IsDeletedColumn).IsEqualTo(false);
foreach(string wordInQuery in wordsInQueryList)
{
q = q.And(InfopathArchive.XmlDocColumn).Like("%" + wordInQuery + "%");
}
return q.ExecuteTypedList();
Then if I look at the query that Subsonic generates:
SELECT (bunch of columns)
FROM [dbo].[Visit]
INNER JOIN [dbo].[InfopathArchive] ON [dbo].[Visit].[VisitId] = [dbo].[InfopathArchive].[VisitId]
WHERE [dbo].[Visit].[IsDeleted] = #IsDeleted
AND [dbo].[InfopathArchive].[XmlDoc] LIKE #XmlDoc
AND [dbo].[InfopathArchive].[XmlDoc] LIKE #XmlDoc
So it ends up that only the last keyword is being searched for.
Any ideas?
First question:
return new SubSonic.Select().From(Visit.Schema)
.InnerJoin(InfopathArchive.VisitIdColumn, Visit.VisitIdColumn)
.Where(InfopathArchive.XmlDocColumn).Like("%" + keywords + "%")
.ExecuteTypedList<Visit>();
Second question:
Pass a List of words in your query to a function that builds a SubSonic query as follows
SqlQuery query = DB.Select().From(Visit.Schema)
.InnerJoin(InfopathArchive.VisitIdColumn, Visit.VisitIdColumn)
.Where("1=1");
foreach(string wordInQuery in wordsInQueryList)
{
query = query.And(InfopathArchive.XmlDocColumn).Like("%" + wordInQuery + "%")
}
return query.ExecuteTypedList<Visit>();
Obviously this is untested but it should point you in the right direction.
You can do what Adam is suggesting or with 2.2 you can simply use "Contains()" instead of Like("%...%"). We also support StartsWith and EndsWith() :)

Calling an SQL function from a Subsonic.Select

I asked the following question on the subsonic forum, but only seemed to get one response, so I thought I'd post up here as well to see if anyone could shed some more light on the problem...
I wish to create the following SQL statement through SubSonic using the Select tool (or Query tool) .. it uses a custom function called "SPLIT()":
SELECT * FROM VwPropertyList
WHERE VwPropertyList.idCreatedBy = 123
AND VwPropertyList.idCounty = 45
AND 29 IN (SELECT Item FROM SPLIT(DistrictGroupList, ','))
(the last part of this SQL uses the SPLIT function)
My subsonic equivalent looks like the following...
Dim mySelect As New SubSonic.Select
mySelect.From(VwPropertyList.Schema)
mySelect.Where(VwPropertyList.Columns.IdCreatedBy).IsEqualTo(123)
mySelect.And(VwPropertyList.Columns.IdCounty).IsEqualTo(45)
mySelect.And(29).In(New SubSonic.Select("Item").From("SPLIT("
&
VwPropertyList.Columns.DistrictGroupList
& ", ',')"))
This doesn't work though due to the last part .. how can I add "AND 29 IN (SELECT Item FROM SPLIT(DistrictGroupList, ','))" into my Subsonic.Select ?
The response I got from the subsonic forum suggested I do away with Subsonic.Select and replace with hard-coded InlineQuery() statements .. like:
Dim SQL as String = "Select " &
VwPropertyList.Columns.Item SQL = SQL
& " From " &
VwPropertyList.Schema.TableName SQL =
SQL & " Where " &
VwPropertyList.Columns.IdCreatedBy & "
= #CreatedBy " SQL = SQL & " And " & VwPropertyList.Columns.IdCounty & " =
#County " SQL = SQL & " And
#DistrictGroup IN (Select Item From
SPLIT(DistrictGroupList,',')"
Items =
SubSonic.InlineQuery().ExecuteTypedList(Of
MyItem)(SQL, 123,45,29)
I would prefer to use SubSonic.Select if possible though so that I can avail of the paging functionality etc.
Any ideas?
You could do John's suggestion or you could write the SQL using our InlineQuery - which allows you to write raw SQL and pass in params:
var qry=new InlineQuery("SELECT * FROM table WHERE column=#param",value)
You could try to use the original query object (pre 2.1) like so (untested, from memory):
Query q = new Query(VwPropertyList.Schema.TableName);
q.WHERE("29 IN (SELECT Item FROM SPLIT(DistrictGroupList, ','))");
// pass q.ExecuteReader() to the Load() method of your view.
I would suggest that you use the original Query object as you are looking to get paging. Inline Query does not have any methods that allow paging.
If you absolutely wanted to use Subsonic.Select you could mesh the two ideas and run an Inline Query to get the list of values and then use a Regular Subsonic.Select and pass the retrieved values to the select case but then you would be making two trips to the db.
On a side note I prefer reading Subsonic.Select statements written using the fluent interface that it is namely
SubSonic.Select.AllColumnsFrom()
.Where(VwPropertyList.Columns.IdCreatedBy).IsEqualTo(123)
.And(VwPropertyList.Columns.IdCounty).IsEqualTo(45)
.ExecuteAsCollection();
thanks for the responses.
I ended up doing InlineQuery and just re-wrote the paging code that's normally produced by Subsonic.Select ... not the best solution but it seems to work.
It would be good if I could have done something like this though:
Dim s As New SubSonic.Select
s.From(VwPropertyList.Schema)
sWhere(VwPropertyList.Columns.IdCreatedBy).IsEqualTo(123)
sAnd(VwPropertyList.Columns.IdCounty).IsEqualTo(45)
s.And(29).In(New
InlineQuery("(SELECT Item FROM
SPLIT(DistrictGroupList, ','))"))

Resources