how to select the earliest time from a datetime database field? - c#

My database has a table with an userId, an userName, a number field that saves an ID for each datetime and a datetime field that records every time the user logs-in and logs-out.
The thing is that logs comes from a fingerprint catcher, and the software that controls the logs is not programmed for avoiding duplicate logs. So, an user can put his finger and save a log-in/log-out hour each time.
My mission is to create a program that would split the datetime field's data in two new datetime fields in another database, one for the log-in hours and another for the log-outs. To achieve that I have to use the ID field that stores a 0 value for the log-ins and 1 to 5 for the log-outs, but I'm out of ideas on how to avoid the duplicates. And if you can give me a good hint on how to achieve the split in a smooth way, it would be lovely.
I have to use ms acces 2007, visual studio 2012 and c# language. Thanks in advance for your attention.
PD: I'm from colombia, thats why my english is a little messy and old.
EDIT: here is an example of my table.
|IdUser||||||||RecordTime||||||||||||||||||||||||||||||||| RecordType |
|399---||||||||28/04/2016 06:55:36 a.m.|||||----- 0----------|
|399---||||||||28/04/2016 06:57:32 a.m.|||||------0----------|
|399---||||||||28/04/2016 05:07:15 p.m.|||||------1----------|
|399---||||||||28/04/2016 05:16:33 p.m.|||||------1----------|
|399---||||||||02/05/2016 07:04:02 a.m.|||||------0----------|
|399---||||||||02/05/2016 05:15:53 p.m.|||||------1----------|

Well, I don't know how big this database of yours is and wether it would be possible to do a cron job every week/day to port the data into the new Database, but i'm going to try explain the concept of my solutions. It's up to you to implement it.
I would use the following method:
Read all the logs of one User into an array with the following fields (If there is too much data, select ranges of datetime with every pass)
Sort that array
-> This should give you changing rows in the RecordType (eg. 0, 2, 0, 1, 0, 5..)
Then write that array (Chronologicaly!) into the new database which has a Unique ID key.
Then you remove this data from the old database in order to not port the same data twice.
Run this every day/week with a cronjob.
It's up to you to implement it. But that is the strategy i would use.
Then you should end up with the following database:
ID|||||IdUser||||||||RecordTime||||||||||||||||||||||||||||||||| RecordType |
1|||||399---||||||||28/04/2016 06:55:36 a.m.|||||----- 0----------|
2|||||399---||||||||28/04/2016 06:57:32 a.m.|||||------0----------|
3|||||399---||||||||28/04/2016 05:07:15 p.m.|||||------1----------|
4|||||399---||||||||28/04/2016 05:16:33 p.m.|||||------1----------|
5|||||399---||||||||02/05/2016 07:04:02 a.m.|||||------0----------|
6|||||399---||||||||02/05/2016 05:15:53 p.m.|||||------1----------|
I hope this helps.

First, the idea of taking two different types of data from a table, without the proper identification, is wrong. Different types of data should always be in different tables.
My boss (i do not know how), resulted to be very illustrated in the ways of programing, and he, after clarifying his needs, gave me a way to make this solution to work:
First, you take the table, and use it to fill an array of any kind, in my case, a DataGridView:
try
{
huella.Open();
OleDbCommand comando = new OleDbCommand();
comando.Connection = huella;
string consulta = "select [User].IdUser,[User].IdentificationNumber,[User].name,[Record].RecordTime," +
"[Record].RecordType from [User] inner join [Record] on [User].IdUser = [Record].IdUser " +
"where " + "[Record].IdUser=#01 and [Record].RecordTime between #time1 and #time2 order by [User].IdUser asc,[Record].RecordTime asc";
comando.CommandText = consulta;
comando.Parameters.AddWithValue("#01", IDcm.Text.ToString());
comando.Parameters.AddWithValue("#time1", dateTimePicker1.Value.Date);
comando.Parameters.AddWithValue("#time2", dateTimePicker2.Value.Date);
OleDbDataAdapter datos = new OleDbDataAdapter(comando);
// using( OleDbDataReader lector = comando.ExecuteReader())
tabla = new DataTable();
datos.Fill(tabla);
//MessageBox.Show(""+tabla);
clu.DataSource = tabla;
}
catch (Exception ex)
{
MessageBox.Show("ERROR " + ex);
}
finally
{
huella.Close();
}
Then, you loop throughout the array's data, assigning the first value of the array to a variable. Inside this loop, you start another loop, to assign the second value of the array to another variable, and finally, you compare this two variables, to assign them to their respective places (following your own criteria):
StreamWriter archivo = new StreamWriter("D:\\MAXIMUM PC.csv", true);
{
archivo.WriteLine('"' + "usuario" + '"' + ";" + '"' + "Hora de entrada" + '"' + ";" + '"' + "Hora de salida" + '"' + ";" + '"' + "Tiempo" + '"' + ";" + '"' + "Pago" + '"');
for (i = 0; i < rows; i++)
{
//assign the first variable, in my case, DateTime data types
fechaHora = Convert.ToDateTime(clu.Rows[i].Cells[0].Value.ToString());
for (j = i + 1; j < rows; j++)
{
//assign the second variable
fechaActual = Convert.ToDateTime(clu.Rows[j].Cells[0].Value.ToString());
if (fechaHora.Date == fechaActual.Date)
{
//here i start the compare process
if (fechaHora.TimeOfDay != fechaActual.TimeOfDay)
{
tiempo = fechaActual.Subtract(fechaHora);
// if the dates are the same, but their time is different..
if (tiempo.TotalHours > 7 && fechaHora.TimeOfDay > fechaActual.TimeOfDay)
{
//if the timespan between the times is over 7 hours and the first date is over the second....
entrada = fechaHora;
salida = fechaActual;
pay = Convert.ToDouble(tiempo.TotalHours * hourPay);
archivo.WriteLine(usuario + ";" + entrada + ";" + salida + ";" + tiempo.TotalHours + ";" + pay);
}
//if the timespan between the times is over 7 hours and the second date is over the fist....
else if (tiempo.TotalHours > 7 && fechaHora.TimeOfDay < fechaActual.TimeOfDay)
{
entrada = fechaHora;
salida = fechaActual;
pay = Convert.ToDouble(tiempo.TotalHours * hourPay);
archivo.WriteLine(usuario + ";" + entrada + ";" + salida + ";" + tiempo.TotalHours + ";" + pay);
}
//if the timespan between the times is under 2 hours and the first date is under or equal the second....
else if (tiempo.TotalHours < 2 && fechaHora.TimeOfDay <= fechaActual.TimeOfDay)
{
error = fechaActual;
}
}
}
}
}
}
Thanks for all your help, i hope this will be useful.

Related

Converting store procedure data to a csv. I am trying to figure out how to use the commas and quotations for the fields that are empty

sb.AppendLine("Employee Id,First Name,Last Name,Email,Username,Password,Role,Group Name,Country Code, Supervisor Id, Hire Date, Birth Date");
for (int i = 0; i < dt.Rows.Count; i++)
{
String[] empid = dt.Rows[i]["EmpId"].ToString().Split(new Char[] { '-' });
sb.AppendLine(Convert.ToInt32(empid[0]).ToString("000000") + "," + dt.Rows[i]["FirstName"] + "," + dt.Rows[i]["LastName"].ToString().Replace(",", " ") +
",," + dt.Rows[i]["Email"] + ",reward," + dt.Rows[i]["Role"] + ",CCCC," + ",," + ",," + dt.Rows[i]["EmployeeHireDate"] + "," + dt.Rows[i]["EmployeeBirthDate"]);
}
email field needs to be empty,
username needs to be the email,
country code needs to be empty,
supervisor id needs to be empty,
Replace this segement:
+ ",CCCC," + ",," + ",," +
with this:
+ ",CCCC,,," +
But you'll really do MUCH better with a dedicated csv library, of which there are several good options on NuGet.
Additionally, if you're using StringBuilder because you heard it's faster, remember that faster is relative. StringBuilder is faster than string concatenation for this kind of work, but if you're ultimately going to writing to a network stream, file, or web response you'll do even better using a StreamWriter

c# transfer list items to listbox [duplicate]

This question already has answers here:
Binding Listbox to List<object> in WinForms
(8 answers)
Closed 3 years ago.
I write a program, it is necessary to switch the current status in it, as well as it is necessary to plan it when you plan an event, it is perceived as an object, the object has its own fields, such as the start time and end time of the event, I want this object to be output when generated sheet boxing.
Tell me how can this be done?
List<ChangeStatus> events = new List<ChangeStatus>();
private void toPlanButton_Click(object sender, EventArgs e)
{
string comboBoxTypeNumber = comboBoxType.SelectedItem.ToString();
DateTime Time = new DateTime();
Time = dateTimePicker1.Value;
DateTime longTime = new DateTime();
longTime = dateTimePicker2.Value;
ChangeStatus statusEvent = new ChangeStatus();
statusEvent.StartEvent = Time;
statusEvent.LongEvent = longTime;
statusEvent.TypeEvent = comboBoxTypeNumber;
events.Add(statusEvent);
TimeComparer tc = new TimeComparer();
events.Sort(tc);
}
How to display an object in listbox?
It is necessary to display a list of objects, because in the future I want to make editing objects
listBoxEvent.Items.Add("type: " + statusEvent.TypeEvent + ";" + " start: " + statusEvent.StartEvent + ";" + " long: " + statusEvent.LongEvent + " min;"); - work
You can use System.Linq Linq to get the string text and can call the AddRange() method on Items collection like
List<string> listData = events.Select(x => "type: " + x.TypeEvent + ";" + " start: " + x.StartEvent + ";" + " long: " + x.LongEvent + " min;").ToList();
listBoxEvent.DataSource = listData;

ASP.NET SQL Query One of Many Columns Undefined

General Description: Single SQL query of multiple SQL databases (through joins) returns all but one item from all but one database. Item not being returned is joined via an item that can, and sometimes is, null.
Specific Description:
I am continuing development of an internal ticketing system for work. I just started with C#, SQL and web development about a month ago, so I am still wrapping my head around all of the interconnections and syntax of Jquery, SQL, C#, and MVC.
Currently I am trying to display an SQL query in a table to show brief information for our tickets to support members. I have everything being displayed except "CircuitDescription" which is a pretty important element in order for support to differentiate between circuits. It is coming through on the table as "undefined" which I have gathered is the JQuery response for an initialized variable. All other values are coming through on the web page.
Running the SQL query through Microsoft SQL Server Management Studio displays the column with the circuit description.
Disclaimer:
While searching for this I have seen posts discouraging multiple database queries, but this is how the program was written before so I want to keep my code as similar to what has been done so far as possible.
So if we could jump past the part where it is implied I am an idiot (as is my only experience asking questions on stackoverflow) that would be lovely.
If you help me solve this, and help me learn why what you suggest works, then you can feel free to imply or directly call me anything you like.
Code:
C# / SQL Query:
-The join statements are combining the lists by a numeric value from DB "Tickets" with a numeric value from the other databases. Those databases are holding 2 columns, the numeric value and a corresponding string description.
-The full outer join is combining the list by a numeric circuitID from the tickets to a numeric circuitID in the circuits database.
-The circuit database holds the circuit description I am struggling with.
-Some circuitID values are null, which I suspect may be why this is not working. The other join statements that I am receiving data in connection to are all not null.
public static async Task<List<Ticket>> GetAllTicketsForCustomerAsync(DBAccess db, int customerID)
{
var cmd = "select TicketID, Tickets.DateCreated, Tickets.DateResolved, Tickets.CustomerCircuitID, CircuitDescription, TicketTypeDesc, BillingStatusDescription, TicketStatusDescription " +
"from Tickets " +
"join TicketTypes on Tickets.TicketTypeID = TicketTypes.TicketTypeID " +
"join TicketStatusTypes on Tickets.TicketStatus = TicketStatusTypes.TicketStatus " +
"join TicketBillingStatusTypes on Tickets.BillingStatus = TicketBillingStatusTypes.BillingStatus " +
"full outer join CustomerCircuits on Tickets.CustomerCircuitID = CustomerCircuits.CustomerCircuitID " +
"where Tickets.CustomerID = " + customerID +
"order by Tickets.TicketID DESC";
var table = await db.ReadTableAsync(cmd);
return (from DataRow row in table.Rows select db.AssignFromRow<Ticket>(row)).ToList();
}
JQuery:
-Ternary operator for circDesc is to list any tickets without a circuitID as "NonSpecific" for their circuit description. Otherwise they should display the circuit description that is currently coming through as "Undefined"
function buildPartialCustomerTicketsTable(tickets) {
var table = "";
var maxSize = (tickets.length < 5) ? tickets.length : 5;
for (var i = 0; i < maxSize; i++) {
var t = tickets[i];
var circDesc = (t.CustomerCircuitID == null) ? "Nonspecific" : t.CircuitDescription;
var rowClass = ((i % 2) == 0) ? "listRowNormal" : "listRowAlternate";
table += "<tr class='" + rowClass + "'>"
+ "<td class='listElement'><a href='#' onclick='viewTicket(" + t.TicketID + ",true)'>update</a></td>"
+ "<td class='listElement'>" + t.TicketStatusDescription + "</td>"
+ "<td class='listElement'>" + formatDate(t.DateCreated) + "</td>"
+ "<td class='listElement'>" + formatDate(t.DateResolved) + "</td>"
+ "<td class='listElement'>" + circDesc + "</td>"
+ "<td class='listElement'>" + t.TicketTypeDescription + "</td>"
+ "<td class='listElement'>" + t.BillingStatusDescription + "</td>"
+ "<td class='listElement'>" + t.TicketID + "</td>"
+ "</tr>";
}
return table;
}
Requested Code:
public T AssignFromRow<T>(DataRow row) where T : new()
{
var rec = new T();
this.AssignFromRow(row, rec);
return rec;
}
public void AssignFromRow(DataRow row, object rec)
{
if (row == null || rec == null)
{
return;
}
// Look at all of the properties in the record
PropertyInfo[] recprops = rec.GetType().GetProperties();
foreach (PropertyInfo pi in recprops)
{
// default the sql column name to the property name
string columnName = pi.Name;
// skip any read only parameters
if (!pi.CanWrite)
{
continue;
}
// Check for a mapping attribute. This attribute can change the name of the table column name from the default.
var customAttrs = pi.GetCustomAttributes(typeof(MappingAttribute), false);
if (customAttrs.Length > 0)
{
var mapping = (MappingAttribute)customAttrs[0];
if (!string.IsNullOrEmpty(mapping.ColumnName))
{
columnName = mapping.ColumnName;
}
}
// If the row does not have this element name then skip it
if (!row.Table.Columns.Contains(columnName))
{
continue;
}
// If the DataRow has a value with the same name, and it is not null, then assign it
object dbval = row[columnName];
if (dbval != null && !(dbval is DBNull))
{
pi.SetValue(rec, dbval, null);
}
}
}

CSV To SQL Converter

I'm currently having some issues with my CSV to SQL Converter. With this being my third week of learning C# I'm starting to grasp some stuff but this is going over my head a bit.
What I'm trying to do is have the Top row/Titles taken down split into each individual title and then for the SQL code through that rather than entering it manually like I've done. Below you can see some of my code that I've built so far.
private void Form1_Load(object sender, EventArgs e)
{
try
{
// your code here
string CSVFilePathName = #"C:\\CSV\\reg.csv";
string[] Lines = File.ReadAllLines(CSVFilePathName);
string[] Fields;
//1st row must be column names; force lower case to ensure matching later on.
// get regs from filename
// get fieldnames from Lines[0] (first line of file)
// create a loop for fields array
string hdr = Lines[0];
for (int i = 1; i < Lines.Length; i++)
{
Fields = Lines[i].Split(new char[] { ',' });
CSVTextBox.AppendText(Fields[0] + "," + Fields[1] + "," + Fields[2] + "," + Fields[3] + Environment.NewLine);
// need a for loop for each field
// for (
SQLTextBox.AppendText("INSERT INTO[dbo].[REGS]([SESTYPE],[REG],[LFL],[SUBVER]) VALUES('" + Fields[3] + "'" + Fields[0] + "'" + Fields[1] + "'" + Fields[2] + ")" + Environment.NewLine);
// }
}
}
catch (Exception ex)
{
MessageBox.Show("Error is " + ex.ToString());
throw;
}
}
This all runs at the moment, I'm just struggling to get the titles to become part of the code. Any help would be appreciated.
Cheers,
First: Remove the try catch. If you get an Exception, you should read, understand and clear off.
For your SQLTextBox: I recommend to use the String.Format function. This allows you to create strings with different values, but is much, much easier to read.
For the titles: Use your variable hdr This should contain the title. Then you can split it via string.Split(',') or string.Split(';'), depending on your delimiter

Programmatically Format Generated CodeDom Code

How can I make sure the CS generated from code like the following is formatted nicely, i.e as if we pressed CTRL+K+D? It is C#
We are doing something along the lines of:
CodeMemberMethod membMethod = new CodeMemberMethod();
membMethod.Attributes = MemberAttributes.Static | MemberAttributes.Public;
membMethod.ReturnType = new CodeTypeReference("IEnumerable<" + TableNameAsSinglular + ">");
membMethod.Name = "Get" + TableName;
membMethod.Statements.Add(new CodeSnippetStatement(DataBaseContext + " dcontext = new " + DataBaseContext + "(ConnectionString);"));
membMethod.Statements.Add(new CodeSnippetStatement("var records = from record in dcontext." + TableName + " select new " + TableNameAsSinglular + "{"));
int iCount = 0;
//Add columns fields
foreach (DataRow dr in sqlTable.Rows)
{
if (iCount == 4)
break;
string strColName = dr["ColumnName"].ToString().Replace(" ", "");
membMethod.Statements.Add(new CodeSnippetStatement(strColName + "=" + "record." + strColName + ","));
iCount++;
}
membMethod.Statements.Add(new CodeSnippetStatement("};"));
CodeDom is really for runtime code generation. If you are looking to generate code at design time or compile time, you should use T4 templates.
T4 lets you format the code output exactly how you want it to appear:
http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx
In Visual Studio, go to
Tool -> Opetions-Text Editor->C#-> Formatting
Ctrl-K-D will use the settings there to format the code.

Categories