Creating a database when installing an SAP Business 1 Add on - c#

I am creating an SAP Business one add-on payroll application - EIMPayroll. I have created an .ard file and I am able to install this add-on in SAP, ie, going to the add on manager and registering the payroll application using the .exe and .ard files.
However, on the machine that I install this add-on on, I have to manually import/create the Microsoft SQL server database "Eim_payroll.bak" on the computer for this add-on to run.
My question is, is there a way I can write the sql query to create the database and tables needed to run this application on a C# file and then package it together into the ard file such that it installs when I install the add-on in SAP?
I create the ard file using Visual Studio 2010 and using the SAP B1 AddOnInstaller .NET Wizard. My add-on is in C#
Any help will be appreciated, including links on examples of how this is done.

Not sure what exactly you are asking. I believe you want to create user tables and user defined fields when registering the add-on in SAP.
Try this, it may work. For creating tables:
ousertable = ocompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oUserTables)
ousertable.TableName = "OEMP"
ousertable.TableDescription = "Employee Header"
lretcode = ousertable.Add
If lretcode 0 Then
ocompany.GetLastError(lerrcode, serrmsg)
sbo_application.MessageBox(serrmsg)
End If
For creating table fields:
ouserfield = ocompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oUserFields)
ouserfield.TableName = "#OEMP"
ouserfield.Name = "empid"
ouserfield.EditSize = "5"
ouserfield.Type = SAPbobsCOM.BoFieldTypes.db_Numeric
ouserfield.Description = "Employee id"
lretcode = ouserfield.Add
If lretcode 0 Then
ocompany.GetLastError(lerrcode, serrmsg)
sbo_application.MessageBox(serrmsg)
End If
Cheers

Related

C# Executing a query and getting data out of an Access Database (accdb) without using ACE.OLEDB

I'm writing a WPF application.
Trying to use the normal method of getting a connection returns an error similar to: "The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine."
ACE.OLEDB has never been installed on this machine so this error makes sense.
I'm trying to create this application in a way so that our users won't need to contact IT to have the application installed. Getting IT involved is a no go situation and the project will be abandoned.
Another team has an Access database (accdb) that I want my application to extract information (only read, no insert or update). I talked to the team and they won't convert this database back to an earlier version (mdb).
After my research I assume that installing ACE.OLEDB without using Admin privileges is impossible. Because of this and my application requirement of not requiring admin privileges I need to start looking for "Mutant"/Dirty solutions that don't involve ACE.OLEDB.
I tried using power-shell but I'm getting the same problems as I had with C# (requires IT to install ACE.OLEDB).
I have two potential solutions. One write a VBA script that opens up the database and dumps a query result into a file. My C# application would call this VB script and then parse the created file.
The second option is to create a new Access process using Process.Start(fullFilePath) and somehow pass the command to execute a query and somehow pass the results back to the executing application (either via a method return or first to a file).
How would you get the data out?
Is there a way for C# to duplicate the DB file and convert it from (accdb -> mdb)?
This is the second question I ask that is very similar.
C# Connecting to Access DB with no install
The difference between the two (to prevent this is a duplicate question) is that in the previous question I was looking for ways to install ACE.OLEDB without admin privileges while here I'm just looking for any other work around.
Found a workaround. It uses Microsoft.Office.Interop.Access found in NuGet.
var accApp = new Microsoft.Office.Interop.Access.Application();
accApp.OpenCurrentDatabase(#tests.DatabasePath);
Microsoft.Office.Interop.Access.Dao.Database cdb = accApp.CurrentDb();
Microsoft.Office.Interop.Access.Dao.Recordset rst =
cdb.OpenRecordset(
"SELECT * FROM Users",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenSnapshot);
while (!rst.EOF)
{
Console.WriteLine(rst.Fields["username"].Value);
rst.MoveNext();
}
rst.Close();
accApp.CloseCurrentDatabase();
accApp.Quit();

Can not connect to ENCRYPTED Access db (accdb) from VSTO (Excel Add-In) - but can from Console-App

From within an VSTO Excel Add-In I tried to connect to an encrypted Access Database (accdb) using OleDbConnection. (I tried on Excel 2010 and 2016 with different VSTO templates)
I get the Error: System.Data.OleDb.OleDbErrorCollection: 'Not a valid password.'
The Source of the Exception is: "Microsoft Access Database Engine".
The Exception does not contain any inner exception.
The code runs without problems:
from within the Add-In if the targeted database is NOT encrypted.
from a console app even if the accdb is encrypted.
So there is no problem with the connection string, the path or the password.
What is different if the code is run in the context of an Add-In?
I found that some people faced a similar problem (the same error message), when trying to connect to an encrypted accdb from ASP.NET and the permissions for the web process were not correct. Could this be a hint? IMHO the Add-In should run with user privileges, so this should not be the cause (and as described above, the connection to the database can be established, therefore the file opened, as long as the accdb is not encrypted)...
public void TestAccessConnect()
{
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source=C:\temp\encryptedDb.accdb;" +
#"Jet OLEDB:Database Password=1234;";
using (var oleDbConn = new OleDbConnection(connString))
{
oleDbConn.Open(); // <---- triggers the following error
// Error: { System.Data.OleDb.OleDbErrorCollection}
// Source: "Microsoft Access Database Engine"
// Message: "Not a valid password"
}
}
I did not find anything concerning my problem on the internet and I am running out of ideas. Is this a (known) bug on the MS side?
Any advice on where to look is highly appreciated.
Update 2019/05/17:
I found that if I encrypted the accdb in "legacy encryption", the connection works! :-(
To reproduce:
In Access:
Decrypt the database (DB must be opened exclusively)
Go to File -> Options -> Client-Settings: There scroll to the "Advanced" section and tick "Legacy encryption" (instead of "Standard" - which is set by default)
Close the database (might be optional)
Reopen the database exclusively
Encrypt the database.
Et voilĂ  - now the database can be opened using the password from the Add-In.
Dear MS-guys - what the heck! The non working "default" encryption is there at since Office 2010 at least.
In addition: I did tried to connect directly to the accdb from Excel 365. Data -> Get Data.
-> Database ->Access. Non encrypted (OK), Encrypted (Fail)
-> Other Sources -> OLEDB: (here you can provide a connection string). Non encrypted (OK), Encrypted (Fail)
-> Other Sources -> ODBC: (Set up a new ODBC-Connection, here you get to see some really cool dialog boxes from the last century): Non encrypted (OK), Encrypted (OK)
Well, it seems that one has to accept that Microsoft can't properly integrate their own database to their office suite. And hey, it's only been about 10 years than this is not working...
Just to make sure that it's not something Excel specific, I also created an Add-In for Word. Same experience.
So basically I can connect either by changing the encryption model (not very practical because there are many instances out there), or by using and ODBC-Connection (no good fit because I want to use EF Core - in this case for Access - (i know, i know, ... Access is about to be phased out)) or by just directly using ADODB or by remoting Access.
But, I still have the feeling that the .NET class SHOULD behave like a .NET class - even if it's hosted in an Office Application.
Does anybody have an idea what could stop this simple command from working?
Update No2 2019/05/17:
I put the connection code in a new DLL project. Then I have an Add-In project and a Console-Application. Both contain basically the same two lines of production code:
var ac = new AccessConnectTest(); // <- class in own assembly
ac.TestAccessLogin();
Console works.
Add-In does not.
How is this possible? Does office fiddle with Assembly resolution?

C# Project - InstallShield , MySql error when run after installation

I have a project in C# which is created in Visual Studio 2013. I want to create an installer using Install Shield free version. I created an installer and trying to run it on other computer but, when I run it and trying to log into program, I have problems about mysql database. Error message is:
Unhandled exception has occured in you application. If you click Continue, the application will ignore this error and attempt to continue. If you click Quit, the application will close immediately.
Cannot connect.
If I click on details button, I have a serie of errors which refers on Mysql. Example:
System.Exception: Cannot connect ---> MySql.Data.MySqlClient.MySqlException: Unable to connect to any of the specified MySQL hosts.
at MySql.Data.MySqlClient.NativeDriver.Open()
at MySql.Data.MySqlClient.Driver.Open()
at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings)
at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()
at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()
at MySql.Data.MySqlClient.MySqlPool.GetConnection()
at MySql.Data.MySqlClient.MySqlConnection.Open()
at simulator.ConnConfig.getConnection()
simulator is the name of the project. ConnConfig is a class where is the connection and getConnection() is a function from ConnConfig which return connection. II tried to install on another computer .NET Framework 4.5.2, SQL Server, but also didn't worked.
In my project, I use localhost server where I have a database with 2 tables. My question is, is there any possibility to add that localhost database to installer and use it on another computer? And what redistributables requires this operation? Also, I have installed on computer .NET Framework 4.5, Sql Server 2012..but when I try do add them in InstallShield via Redistributables, but it keeps saying that Needs to be downloaded. Why?
UPDATE
I have this Class where I make the conenction. But I receive error: Additional information: Illegal characters in path. at that line:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SQLite;
namespace simulator
{
class ConnConfig
{
private static string conn = "Data Source=c:\aplicatie.db;Version=3;Password=myPassword;";
public static SQLiteConnection connect = null;
private ConnConfig()
{
}
public static SQLiteConnection getConnection()
{
SQLiteConnection connect = null;
try
{
connect = new SQLiteConnection(conn);
connect.Open();// here I receive the error
return connect;
}
catch (SQLiteException e)
{
throw new Exception("Cannot connect", e);
}
}
}
}
UPDATE 3
In that class I make the connection to database. In the other forms I just use tables and their data. For connection to program, I use a login form which uses this class to getConnection(). I created that database by adding an ADO.NET in simulator project. And with that, it comes those 2 tables that I already have in localhost server. So, Is ok if I have to create another empty database with new tables, but where to include that code or how to use it, because I don't get how that script works..where should I put it?
If your database is going to be installed on each client and your tables are not massive you might want to look at something lighter like SQLite which doesn't need any installation just the dlls and is very fast and efficient and only runs when your program does.
As for for the Needs to be Downloaded issue, it seems you have not setup your prerequisite correctly, you an correct this by following the steps in this article
Adding InstallShield Prerequisites, Merge Modules, and Objects to Basic MSI and InstallScript MSI Projects
You might want to look into determining if MySQL is the right solution for you.
SQLite vs MySQL vs PostgreSQL: A Comparison Of Relational Database Management Systems
And to see the limitations of SQLite SQLite
Because honestly seems like overkill to install MySQL on every system. If you had one server with MySQL on the network, okay. But on every system seems like a bad idea.
As far as connecting to an SQLite database here is a List of Connection Strings for SQLite
See this topic on how to create Databases and tables Create SQLite Database and table
My guess is your program doesn't bundle up the database alongside the setup upon deployment. This may be due to the fact that you didn't mark your database as a Data File in the Project Files. Try this, right click on your project name in Solution Explorer and select Properties from Menu. From the horizontal tabs click on the Publish Tab. Under Install Mode and Settings click the Application Files button. A dialog box appears with all Application files. Set your database Publish Status to Data File from the drop down on the corresponding cell. This way your database will be bundled together with the setup upon publishing. Hope this helps.
You can access SQLite via ODBC.

Change SSRS data source of report programmatically in server side

Today, for each customer, we deploy same SSRS reports folder and data source folder.
The difference between these folders are the name of each folder and the connection string of the data source.
We are using Report Server 2008 R2.
Is it possible to maintain only one reports and data source folder and change programmatically its connection string on server-side before the report been rendered?
If not, Is it something that can be achieved by changing some logic in reports?
Today we use "shared data source" option.
This is something we've done in our environment - we maintain one set of reports that can be deployed at any client with their own configuration.
You've got a couple of options here. Since you're using a Shared Data Source this makes things easier as you won't need to define a Data Source for each report.
1. Use the rs.exe utility and a script file
rs.exe at Books Online
This program allows you to create script files (in VB.NET) that can interact with a Report Server Web Service. You create a script file (e.g. Deploy.rss) and call the rs.exe program with various parameters, including any custom ones you define:
rs.exe -i DeployReports.rss -s http://server/ReportServer -v DatabaseInstance="SQL" -v DatabaseName="ReportDB" -v ReportFolder="ClientReports"
So this would call a script DeployReports.rss, connect to http://server/ReportServer, with three user defined parameters which could be used to create a data source and the report folder.
In the scipt file you could have something like this:
Public Sub Main()
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
CreateFolder(reportFolder, "Report folder")
CreateFolder(datasourceFolder, "Data source folder")
CreateDataSource()
End Sub
Which can then make Web Service calls like:
rs.CreateFolder(folderName, "/", Nothing)
'Define the data source definition.
Dim definition As New DataSourceDefinition()
definition.CredentialRetrieval = CredentialRetrievalEnum.Integrated
definition.ConnectString = "data source=" + DatabaseInstance + ";initial catalog=" + DatabaseName
definition.Enabled = True
definition.EnabledSpecified = True
definition.Extension = "SQL"
definition.ImpersonateUser = False
definition.ImpersonateUserSpecified = True
'Use the default prompt string.
definition.Prompt = Nothing
definition.WindowsCredentials = False
Try
rs.CreateDataSource(datasource, datasourcePath, False, definition, Nothing)
Console.WriteLine("Data source {0} created successfully", datasource)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
You haven't specified what version of Reporting Services you're using, so I'm assuming 2008. Please note that there are multiple endpoints that can be used, depending on SQL Server version. The 2005/2008 end point is deprecated in 2008R2 and above but is still usable. Just something to bear in mind when writing your script.
2. Call the SSRS Web Service through an application
Report Server Web Service overview
The same calls that are made from the script above can be made in any other application, too. So you'd just need to add a reference to a Report Server Web Service through WSDL and you can connect to a remote service and call its methods to deploy reports, data sources, etc.
So ultimately you're connecting to the Report Server Web Service, it's just the medium used that you need to think about.
Using a script is easier to get running as it's just running a program from the command line, but writing your own deployment application will certainly give greater flexibility. I would recommend getting the script going, so you understand the process, then migrate this to a bespoke application if required. Good luck!
You can use an Expression Based Connection String to select the correct database. You can base this on a parameter your application passes in, or the UserId global variable. I do believe you need to configure the unattended execution account for this to work.
Note: be careful about the security implications. Realize that if you would pass sensitive data (e.g. passwords) into a parameter, that (a) it will go over the wire, and (b) will be stored in the execution log tables for reporting services.

Synchronising databases SQL Server via C#

How do I synchronise a database on one server to the other? I need to do it via C#, not scripts. I was planning to use ADO.NET to retrieve the schema and dataset from one database, but how do I sync it in code?
Thanks
There are various options available to you:
SSIS to Export/Import data between System1 & System2
Mirroring to copy data between System1 & System2
Replication to keep System2 in sync with System1
Scripts for Database Backup/Restore between servers using C# to be the IO glue that scripts the backup on System1, copies the file to System2 and calls the restore script on System2
The easiest option to implement is #4 specially if changes occur to System1 that need to be replicated to System2 (tables, indexes, views, procedures, functions, triggers..etc..etc...)
See Database Mirroring in SQL Server 2005 # SQL Server Performance or Database Mirroring in SQL Server 2005 # Microsoft for mirroring information.
If you need some more enlightment on #4 just reply. Oh, it would help to specify what version of SQL server you are using. This information assumes >=2005 (Yukon, Katmai and possibly Killimanjaro)
Update: I would stay clear of trying to implement your own runtime on this as there are so many variations that just copying between 2 servers requires the ability to do diffs against the objects. Even using the SMO .NET objects this would be an ardous task that would require a lengthy development schedule.
Update 1: The poster is interested in the SSIS version so we will use those instructions.
Start SQL Server Management Studio
Navigate to the chosen database
Right click and Tasks->Export Data
Click Next
Select required source
Click Next
Select destination settings
Click Next
Select either use either tables or Write a query (we will assume use tables)
Click Next
Select the required tables
Click Edit Mappings
Ensure that enable identity insert is selected if required
Ensure Delete/Appends rows is selected as required
Ensure Drop and re-create destination table selected as required
Click Ok
Click Next
Now save this to an SSIS package either into SQL Server or on the filesystem
You can now use DTSExec to execute this package via a scheduler or use the .NET wrapper and call from your own C# runtime
C# Code example from Microsoft Website
using System;
using Microsoft.SqlServer.Dts.Runtime;
namespace RunFromClientAppCS
{
class Program
{
static void Main(string[] args)
{
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());
Console.ReadKey();
}
}
}
Resources
dtexec Books Online (BOL)
SQL Server Import Export Wizard BOL
Visual Walkthru # http://www.accelebrate.com/sql_training/ssis_2008_tutorial.htm
Youtube Videos
Loading & Running SSIS Packages Programmatically
Why would you build this when there are db tools that do it for you?
Look into SSIS, or as it was previously known, DTS.

Categories