C# using mssql2012 import wizard - c#

Is it possible to use the mssql2012 import wizard for databases and tables withing the c# code?
I wanted to write a program with which i can import databases and tables of an access db to a mssql db. Therefore, as a gui, the mssql2012 import wizard works fine, i just need to implement it in c# Code in my project. Are there any prebuilt classes in the .net framework?
Regards

I will suggest you use Bulk Insert. This has already been managed into a .NET class SqlBulkCopy .

If you just want to import data into the database, use SqlBulkCopy. The import wizard does more than just send a batch of data to the server.
Actually, the Import wizard creates and executes an SSIS package with data transformation that extracts data from the source and sends it to the target. It doesn't do anything by itself. The last step of the wizard allows you to save the generated package and use it again, as you would with any other SSIS package.
You can load a saved package and execute it using the code provider in "Loading and Running a Local Package Programmatically". The sample code is very simple:
string pkgLocation;
Package pkg;
Application app;
DTSExecResult pkgResults;
pkgLocation =
#"C:\Program Files\Microsoft SQL Server\100\Samples\Integration Services" +
#"\Package Samples\CalculatedColumns Sample\CalculatedColumns\CalculatedColumns.dtsx";
app = new Application();
pkg = app.LoadPackage(pkgLocation, null);
pkgResults = pkg.Execute();
Console.WriteLine(pkgResults.ToString());
If you want to create a new package each time, you can use the EzAPI library to create a package programmatically, save it and/or execute it. The MSDN blog contains a sample for creating a simple dataflow task:
public class EzOleDbToFilePackage : EzSrcDestPackage<EzOleDbSource, EzSqlOleDbCM, EzFlatFileDestination, EzFlatFileCM>
{
public EzOleDbToFilePackage(Package p) : base(p) { }
public static implicit operator EzOleDbToFilePackage(Package p) { return new EzOleDbToFilePackage(p); }
public EzOleDbToFilePackage(string srv, string db, string table, string file)
: base()
{
SrcConn.SetConnectionString(srv, db);
Source.Table = table;
DestConn.ConnectionString = file;
Dest.Overwrite = true;
// This method defines the columns in FlatFile connection manager which have the same
// datatypes as flat file destination
Dest.DefineColumnsInCM();
}
[STAThread]
static void Main(string[] args)
{
// DEMO 2
EzOleDbToFilePackage p2 = new EzOleDbToFilePackage("localhost", "AdventureWorks", "Address", "result.txt");
p2.DataFlow.Disable = true;
p2.Execute();
Console.Write(string.Format("Package2 executed with result {0}\n", p2.ExecutionResult));
}
}
You should note though that if the generated default mappings aren't suitable for your task, you'll have to define each one separately in code.

Related

How to create the SQlite database when the application is deployed/installed?

I am new to c#/.NET and developing an application with SQlite datbase and entity framework and it is all working fine during testing. I am specifying the below for the filepath to the .db file.
var path = AppDomain.CurrentDomain.BaseDirectory;
On deployment I need the application to create the database fresh, that doesn't contain the test data I was using during development. So I cannot simply copy the current .db file. Can anyone help with code that checks existence of database, and if not it will create new?
You can use this method:
private static void CreateFreshDb(string dbFilePath)
{
// Create the DB file
SQLiteConnection.CreateFile(dbFilePath);
// Create a table
var connectionString = $"Data Source={dbFilePath};Version=3;";
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
string creationScript = "Create Table Person (Id int, Name varchar(20))";
SQLiteCommand command = new SQLiteCommand(creationScript, connection);
command.ExecuteNonQuery();
command.Dispose();
}
}
And call it like that:
string dbFilePath = "C:\\Db\\Database.db";
if (!File.Exists(dbFilePath))
{
CreateFreshDb(dbFilePath);
}
Note that I use the System.Data.SQLite library here.
An appliation that creates databases should be in principle a script that creates databases. If you application has its own business line which requires a database, but it is not intended to create a database at first, better you create it manually outside the code and then simply let the code choose between which database to use between testing and production, via appSettings or similar solution.

C# Not saving data in MS Access Database [duplicate]

I have following C# code in a console application.
Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = "FlowerShop.sdf";
string fileLocation = "|DataDirectory|\\";
DatabaseAccess dbAccess = new DatabaseAccess();
dbAccess.Connect(fileName, fileLocation);
Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
string res = dbAccess.ExecuteQuery(query);
Console.WriteLine(res);
string query2 = "Select * from Products";
string res2 = dbAccess.QueryData(query2);
Console.WriteLine(res2);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
class DatabaseAccess
{
private SqlCeConnection _connection;
public void Connect(string fileName, string fileLocation)
{
Connect(#"Data Source=" + fileLocation + fileName);
}
public void Connect(string connectionString)
{
_connection = new SqlCeConnection(connectionString);
}
public string QueryData(string query)
{
_connection.Open();
using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
using (DataSet ds = new DataSet("Data Set"))
{
da.Fill(ds);
_connection.Close();
return ds.Tables[0].ToReadableString(); // a extension method I created
}
}
public string ExecuteQuery(string query)
{
_connection.Open();
using (SqlCeCommand c = new SqlCeCommand(query, _connection))
{
int r = c.ExecuteNonQuery();
_connection.Close();
return r.ToString();
}
}
}
EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.
It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.
But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.
Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.
Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.
You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.
EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.
Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:
You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.
You can decide not to include the sdf file as part of your project and manage the file location runtime.
If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.
If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).
If you have "Copy always", any changes made during runtime will always be overwritten
Answer Source
Here is a link to some further discussion and how to documentation.

How to insert data into a local datatable in C#? [duplicate]

I have following C# code in a console application.
Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = "FlowerShop.sdf";
string fileLocation = "|DataDirectory|\\";
DatabaseAccess dbAccess = new DatabaseAccess();
dbAccess.Connect(fileName, fileLocation);
Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
string res = dbAccess.ExecuteQuery(query);
Console.WriteLine(res);
string query2 = "Select * from Products";
string res2 = dbAccess.QueryData(query2);
Console.WriteLine(res2);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
class DatabaseAccess
{
private SqlCeConnection _connection;
public void Connect(string fileName, string fileLocation)
{
Connect(#"Data Source=" + fileLocation + fileName);
}
public void Connect(string connectionString)
{
_connection = new SqlCeConnection(connectionString);
}
public string QueryData(string query)
{
_connection.Open();
using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
using (DataSet ds = new DataSet("Data Set"))
{
da.Fill(ds);
_connection.Close();
return ds.Tables[0].ToReadableString(); // a extension method I created
}
}
public string ExecuteQuery(string query)
{
_connection.Open();
using (SqlCeCommand c = new SqlCeCommand(query, _connection))
{
int r = c.ExecuteNonQuery();
_connection.Close();
return r.ToString();
}
}
}
EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.
It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.
But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.
Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.
Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.
You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.
EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.
Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:
You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.
You can decide not to include the sdf file as part of your project and manage the file location runtime.
If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.
If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).
If you have "Copy always", any changes made during runtime will always be overwritten
Answer Source
Here is a link to some further discussion and how to documentation.

How to use variables from C# application in SSIS package

I am new to both VC# and SSIS. But here is my scenario, I have data from multiple projects within a single SQL database i.e. multiproject mode (One SQL database storing data from multiple projects). This data is separated based on proj_ID field. I am trying to create C# application which pulls this proj_id in one of it's combobox fields and runs the SSIS package on the project after I click on Export data button. Now I want to use this project id in SSIS package so that package dataflow should only execute on that project.
I have added this in C# code and not sure if this is correct:
public void button2_Click(object sender, EventArgs e)
{
//Start the SSIS Here
try
{
Microsoft.SqlServer.Dts.Runtime.Application app = new Microsoft.SqlServer.Dts.Runtime.Application();
Package package = null;
package = app.LoadPackage(#"C:\SSIS_Projects\XXX_Project\XXXX_Project\Package.dtsx", null);
Microsoft.SqlServer.Dts.Runtime.Variables myVars = package.Variables;
myVars["projectroot"].Value = projectroot;
myVars["path8"].Value =path8;
myVars["PROJ_NAME"].Value = comboBox1.ValueMember;
myVars["PROJ_ID"].Value = comboBox2.ValueMember;
//Excute Package
// working Microsoft.SqlServer.Dts.Runtime.DTSExecResult results = package.Execute();
Microsoft.SqlServer.Dts.Runtime.DTSExecResult results = package.Execute(null, myVars, null, null, null);
if (results == Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure)
{
foreach (Microsoft.SqlServer.Dts.Runtime.DtsError local_DtsError in package.Errors)
{
Console.WriteLine("Package Execution results: {0}", local_DtsError.Description.ToString());
Console.WriteLine();
}
}
}
catch (DtsException ex)
{
throw new FileNotFoundException("[Package.dtsx not found in directory]", ex);
}
}
P.S: PROJ_ID is main variable to call in package but I might need projectroot, name and path as well.
If this is correct, then How do I define and use these variable in SSIS package?
how to proceed further in SSIS package? I can guess that I have to write script task but again it will take me lot of time to learn and write. If you can guide me and provide some sample code then it will be very helpful.
Thanks in advance.
Vishal
I don't remember why, but I do remember that when I needed to execute an SSIS package with variables from C#, here is the approach that finally worked for me:
Create a job that calls the SSIS package.
Create a table that holds the values of the variables used by the package. The table must also include some kind of "Job Result" column.
Include a step at the beginning of the package that reads the values of its variables from the first row in the table that has NULL for JobResult.
Include a step at the end of the package that updates the JobResult column in the variables table, with "Success", "Failure" or whatever you want, as long as it's not NULL.
In C#, populate the table with the variable values you want, then start the job.
Hope this helps.

How to update existing custom connection manager without breaking existing packages

We have an existing MQ custom connection manager that's currently being used by several existing SSIS packages.
I want to add a new property and modify the code a little bit, but if I do that, it looks like I am breaking everything else (have to redo all of them).
Is there a way where I can get around this without disrupting the existing packages that use it?
Assuming that your you need to edit the SSIS package by adding the property and RUN it. After that you don't need the SSIS package. Following code method should be added to your application and call this method. So all the changes will be applied only to the new package without modifying another package.
Get the SSIS package
Create the copy of it by appending the GUID. so your package name is like PackageName_GUID.dtsx
Add your property.
RUN your SSIS package
OnSuccess full execution. Delete the SSIS package.
Code
public static DtsErrors RunSSISPackage(string packagePath, string MQProperty)
{
* Append the auto generated GUID with the package name for running the SSIS package
*/
string uniqueId = Guid.NewGuid().ToString();
string uniquePackage = Path.GetDirectoryName(packagePath) + #"\" + Path.GetFileNameWithoutExtension(packagePath) + "_" + uniqueId + ".dtsx";
File.Copy(packagePath, uniquePackage);
Package pkg;
Microsoft.SqlServer.Dts.Runtime.Application app = new Microsoft.SqlServer.Dts.Runtime.Application();
pkg = app.LoadPackage(uniquePackage, null);
//MessageBox.Show(srcFileName);
//MessageBox.Show(TPODBConnection);
pkg.Connections["MQConnection"].<<YourPropertyName>> = MQProperty;
//Uncomment this to overwrite the existing file
//Do nothing until you are using a version control system
//app.SaveToXml(packagePath, package, null);
DTSExecResult result = pkg.Execute();
if (result == DTSExecResult.Failure)
{
return pkg.Errors;
}
File.Delete(uniquePackage);
return null;
}

Categories