I have the code below to allow me to add data from a excel sheet directly into a sing given database, now I would like to know how I would be able to call the method multiple times to add data from two different excel file at once, the is a button which calls this method once clicked, using multi-threading.
private void AddToDatabase()
{
using (OleDbConnection connection =
new OleDbConnection(excelConnectionString))
{
connection.Open();
CheckNumeberOfSheets(connection);
}
}
Button code;
private void button1_Click(object sender, EventArgs e)
{
AddToDatabase();
}
May be you can pass a string to your method AddToDatabse like
private void AddToDatabase(string fileName){
if(fileName.Equals("yourfirstFile"))
{
using (OleDbConnection connection =
new OleDbConnection(excelConnectionString))
{
connection.Open();
CheckNumeberOfSheets(connection);
}
}
else if(fileName.Equals("yoursecondfile"))
{
using (OleDbConnection connection =
new OleDbConnection(excelConnectionString2))
{
connection.Open();
CheckNumeberOfSheets(connection);
}
}
}
and then call it like this
private void button1_Click(object sender, EventArgs e)
{
AddToDatabase("yourfirstFile");
AddToDatabase("yoursecondFile");
}
Step 1: create a class named "ClassFiles"
public class ClassFiles
{
private String fileName;
private String excelConnectionString;
public String getFileName()
return fileName;
public void setFileName(String fileName)
{
this.fileName=fileName;
}
public String getExcelConnectionString()
return excelConnectionString;
public void setExcelConnectionString(String excelConnectionString)
{
this.excelConnectionString=excelConnectionString;
}
}
Step 2: In your main class, add the fileName along with excelConnection String like:
public class MainClass{
private void AddFilesToDB(List<ClassFiles>fileDetails){
for(ClassFiles fileDeteil : fileDetails){
using (OleDbConnection connection =
new OleDbConnection(fileDeteil.getExcelConnectionString))
{
connection.Open();
CheckNumeberOfSheets(connection);
}
// as well as u can get the file name..
String fileName=fileDeteil.getFileName();
}
}
public Static void main(string args[]){
List<ClassFiles> addDetails =new ArrayList<ClassFiles>();
//now add the no of files into the list
ClassFiles objFile1=new ClassFiles();
objFile1.setFileName("filename1");
objFile1.setExcelConnectionString("excelConnectionString1");
addDetails.add(objFile1);
ClassFiles objFile2=new ClassFiles();
objFile2.setFileName("filename2");
objFile2.setExcelConnectionString("excelConnectionString2");
addDetails.add(objFile2);
and so on..
then call the function for further process.,
new MainClass().AddFilesToDB(addDetails);
}
hope it ll help you..
Related
How do I put classes in this C# script which saves and loads files. I am currently in process of learning C#. I have to make a project for school with C# which loads and saves files with use of classes. I learned how to work with classes, but I am really getting confused when I have to make use of this in my script:
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
if (open.ShowDialog() == DialogResult.OK) ;
{
StreamReader read = new StreamReader(File.OpenRead(open.FileName));
textBox1.Text = read.ReadToEnd();
read.Dispose();
}
}
private void button2_Click(object sender, EventArgs e)
{
SaveFileDialog save = new SaveFileDialog();
if (save.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
StreamWriter write = new StreamWriter(File.Create(save.FileName));
write.Write(textBox1.Text);
write.Dispose();
}
}
I think the main point of your exercise is to separate responsabilities.
Every class should accomplish one task only.
According to this principle it is good practice to logically split your programs in three levels (UI, Business and Data layer).
There's a lot to discuss on this so i suggest you to have a look to SOLID principles and 3-Tier level architectures
To help you I suggest you to change your code as follows (this example uses three levels but if you use two levels it is good enough and your teacher won't suspect you received a hint)
// You User Interface, should use Business level classes (not data)
class YourForm
{
private readonly YourService _myLogicService;
public YourForm()
{
_myLogicService = new YourService(new YourFilePersistor());
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
if (open.ShowDialog() == DialogResult.OK) ;
{
textBox1.Text = _myLogicService.Read(open.FileName);
}
}
private void button2_Click(object sender, EventArgs e)
{
var toSave = textBox1.Text;
SaveFileDialog save = new SaveFileDialog();
if (save.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_myLogicService.Write(save.FileName, toSave);
}
}
}
// Data Layer: this class has dependencies from file system
// (in future a database can be used but you will not change your business service, just implement the interface)
public class YourFilePersistor : IPersistor
{
public string Read(string filePath)
{
return System.IO.File.ReadAllText(filePath); // Or your code
}
public void Write(string filePath, string fileContent)
{
System.IO.File.WriteAllText(filePath, fileContent); // Or your code
}
}
public interface IPersistor
{
string Read(string filePath);
void Write(string filePath, string fileContent);
}
// Service is your "Business Level" for put your application logic on your domain data
// Business classes uses intefaces to abstract data layer and work without dependencies from components like database, remote apis and so on...
public class YourService
{
private readonly IPersistor _repository;
public YourService(IPersistor repository)
{
_repository = repository;
}
public string Read(string filePath)
{
var data = _repository.Read(filePath);
return data;
}
public void Write(string filePath, string fileContent)
{
var data = fileContent;
// here you could do some logic i.e. to validate your data
if (string.IsNullOrWhiteSpace(fileContent))
{
throw new InvalidOperationException("Data is null");
}
// ---
_repository.Write(filePath, data);
}
}
As the title says, I need to pass a list of hashtables from a regular class to a form class to be rendered in a DataGridView. What I've got so far is this:
namespace somenamespace
{
class aldeloUpdater
{
private static string client = "chanchitos";
private static string establishment = "c1";
static void Main()
{
try
{
var guiForm = new GuiForm(); // Instantiating the Form-derived class.
string deliveriesListResp = getOrders();
Processing...
foreach (...)
{
if ((bool)DBresponse["status"])
{
guiForm.dataGridViewProducts = (List<Hashtable>)DBresponse["deliveriesSaved"]; // Passing the data to the DataGridView.
foreach (Hashtable delivery in (List<Hashtable>)DBresponse["deliveriesSaved"])
{
string updateDeliveryResponse = updatePedidoInDomicilios(delivery["domiciliosOrderId"].ToString(), 2, DBresponse["errmsg"].ToString());
}
}
else
{
Processing...
}
}
guiForm.ShowDialog(); // Showing the form.
More processing...
}
catch (Exception e)
{
Console.WriteLine("Exception details: " + e.ToString());
Console.ReadLine();
}
}
More methods...
}
Now the Form class looks like this:
namespace somenamespace
{
public partial class GuiForm : Form
{
public List<Hashtable> dataGridViewProducts; // Variable used to store the data to be rendered by the DataGridView.
public GuiForm()
{
InitializeComponent();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void GuiForm_Load(object sender, EventArgs e)
{
int index = 0;
foreach (Hashtable product in dataGridViewProducts)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = product["productName"];
dataGridView1.Rows[index].Cells[1].Value = product["userName"];
dataGridView1.Rows[index].Cells[2].Value = product["dateAndTime"];
dataGridView1.Rows[index].Cells[3].Value = product["domiciliosOrderId"];
index++;
}
}
Some more methods.
}
}
For now this code works just fine and the data is shown in the DataGridView, nonetheless I feel like there must be a better way to achieve this goal, it's just that I'm new to C#. I will appreciate suggestions and even more a code sketch of how you would do this in a better way.
Thanks.
I created a method that append data to file .txt and it executes on Button_Click method. But I want to save the data to file not when I click the button but after time automatically (ex. after couple minutes starting from Application_Start). How can I solve my problem?
static public bool appendToFileTxt(string input)
{
try
{
if (File.Exists(nameOfFile))
File.Copy(nameOfFile, nameOfFile + ".bak", true);
using (StreamWriter sw = new StreamWriter(nameOfFile, true)){
sw.WriteLine(input.Replace("\r", ""));
}
return true;
}
catch{
return false;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
appendToFileTxt(newInput);
}
You can use the Timer class for this usage.
// Simulate Application_Start
public static void Main()
{
var appendToFileTimer = new Timer(AppendToFile, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
}
public static void AppendToFile(Object state)
{
Console.WriteLine("Append to file");
}
I'm getting some troubles in the last days to use the SQL Dependency.
With the sample in this link I have ALMOST reach my goal. "Almost" because the event get fired correctly, but also at the startup, when I call the Start method of the MyService class. Here there is my code, but as you can see it's the same (or almost) of the link.
I think I can simply insert a bool value, only to avoid the initialitation event, but I think also that another solution would be better.
SQLWatcher:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public enum SqlWatcherNotificationType
{
Blocking,
Threaded // Launch in another thread so SqlWatcher can immediately start monitoring again.
}
public class SqlWatcher : IDisposable
{
private string ConnectionString;
private SqlConnection Connection;
private SqlCommand Command;
private SqlDataAdapter Adapter;
private DataSet Result;
private SqlWatcherNotificationType NotificationType;
public SqlWatcher(string ConnectionString, SqlCommand Command, SqlWatcherNotificationType NotificationType)
{
this.NotificationType = NotificationType;
this.ConnectionString = ConnectionString;
SqlDependency.Start(this.ConnectionString);
this.Connection = new SqlConnection(this.ConnectionString);
this.Connection.Open();
this.Command = Command;
this.Command.Connection = this.Connection;
Adapter = new SqlDataAdapter(this.Command);
}
public void Start()
{
RegisterForChanges();
}
public void Stop()
{
SqlDependency.Stop(this.ConnectionString);
}
public delegate void SqlWatcherEventHandler(DataSet Result);
public event SqlWatcherEventHandler OnChange;
public DataSet DataSet
{
get { return Result; }
}
private void RegisterForChanges()
{
//Remove old dependency object
this.Command.Notification = null;
//Create new dependency object
SqlDependency dep = new SqlDependency(this.Command);
dep.OnChange += new OnChangeEventHandler(Handle_OnChange);
//Save data
Result = new DataSet();
Adapter.Fill(Result);
//Notify client of change to DataSet
switch (NotificationType)
{
case SqlWatcherNotificationType.Blocking:
OnChange(Result);
break;
case SqlWatcherNotificationType.Threaded:
ThreadPool.QueueUserWorkItem(ChangeEventWrapper, Result);
break;
}
}
public void ChangeEventWrapper(object state)
{
DataSet Result = (DataSet)state;
OnChange(Result);
}
private void Handle_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type != SqlNotificationType.Change)
throw new ApplicationException("Failed to create queue notification subscription!");
//Clean up the old notification
SqlDependency dep = (SqlDependency)sender;
dep.OnChange -= Handle_OnChange;
//Register for the new notification
RegisterForChanges();
}
public void Dispose()
{
Stop();
}
}
and this is MyService class:
public class MyService
{
private static SqlWatcher SqlQueueWatcher;
public static void Start()
{
string connS = MainWindow.dbContext.Database.Connection.ConnectionString + "Password=111;";
//Build the command object we want to monitor (don't include a SqlConnection)
SqlCommand cmd = new SqlCommand();
cmd = new SqlCommand("SELECT CODVEI FROM dbo.ArchivioErogazioni");
cmd.CommandType = CommandType.Text;
//Setup the SQLWatcher
SqlQueueWatcher = new SqlWatcher(connS, cmd, SqlWatcherNotificationType.Blocking);
SqlQueueWatcher.OnChange += new SqlWatcher.SqlWatcherEventHandler(QueueSQLWatcher_OnChange);
SqlQueueWatcher.Start();
}
private static void QueueSQLWatcher_OnChange(DataSet Result)
{
//Do something with the updated DataSet object
Debug.WriteLine("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); ---> ENTERS HERE IN THE INIT PHASE
}
public static void Stop()
{
SqlQueueWatcher.Dispose();
}
}
and this is how I symply call it:
MyService.Start();
Is the bool flag a bad idea? Why does it enter in QueueSQLWatcher_OnChange at startup time?
To fix this issue, you need only to set the notification for that SqlCommand to null.
cmd.Notification = null;
Just try this and i think your problem will be resolved. Enter this line before starting the dependency using the SqlWatcher class
Of course there are many answers for this question,though,I got no clear Idea for my problem.
I'm working on Visual Studio.I have 2 forms as one is weeklyGVadminview and dailyGVadminview..
I wrote a function(method) in dailyGVadminview which is needed now in another form.....
I'm adding my code here..Any ansers will be appreciated in advance thanks.
namespace weeklyattendance
{
public partial class dailyGvAdminview : Form
{
public dailyGvAdminview()
{
InitializeComponent();
}
private void datechanges()
{
string date = dateTimePicker1.Value.ToString("dd/MM/yyyy");
var connectionstring = ConfigurationManager.ConnectionStrings["attendancemanagement"].ConnectionString;
SqlConnection cn = new SqlConnection(connectionstring);
string query = "select count(Employee_id) from employee_details";
cn.Open();
SqlCommand cmd = new SqlCommand(query, cn);
object result =cmd.ExecuteScalar();
txttotalstaff.Text = (result.ToString());
cn.Close();
}
}
}
Form2 code as follows
namespace weeklyattendance
{
public partial class weeklyGvAdminView : Form
{
public weeklyGvAdminView()
{
InitializeComponent();
}
}
private void dateTimePicker1_ValueChanged_1(object sender, EventArgs e)
{
//here I want to call that function or method
}
}
So I would just create a new class and put the method on that class:
public class DbHandler
{
public string DateChanges()
{
string date = dateTimePicker1.Value.ToString("dd/MM/yyyy");
var connectionstring = ConfigurationManager.ConnectionStrings["attendancemanagement"].ConnectionString;
SqlConnection conn = new SqlConnection(connectionstring);
string query = "select count(Employee_id) from employee_details";
conn.Open();
SqlCommand cmd = new SqlCommand(query, conn);
object result = cmd.ExecuteScalar();
var result = result.ToString();
conn.Close();
return result;
}
}
Then in your classes do this:
var dbHandler = new DbHandler();
var result = dbHandler.DateChanges();
I would try and follow some conventions as well. Makes it easier for other programmers to follow what is going on.
You can create object of dailyGvAdminview and call for that try below code :-
namespace weeklyattendance
{
public partial class weeklyGvAdminView : Form
{
public weeklyGvAdminView()
{
InitializeComponent();
}
}
private void dateTimePicker1_ValueChanged_1(object sender, EventArgs e)
{
var form1 = new dailyGvAdminview();
//// call function using this instance
}
}
If you want to access method from outside then make it to Public as shown below :-
public string DateChanges()
{
}
If you want a really GLOBAL and easy solution do this, first you make a static class.
namespace weeklyattendance
{
public static class Obj
{
public static dailyGvAdminview globalDaily;
}
}
Then in your initialize or onLoad code where you create this class just write
Obj.globalDaily = this;
Now you can access this class anywhere in your program with Obj.globalDaily, you can also add whatever else you want in there and access it like that