Connect to AS400 using .NET - c#

I am trying to build a .NET web application using SQL to query AS400 database. This is my first time encountering the AS400.
What do I have to install on my machine (or the AS400 server) in order to connect?
(IBM iSeries Access for Windows ??)
What are the components of the connection string?
Where can I find sample codes on building the Data Access Layer using SQL commands?
Thanks.

You need the AS400 .Net data provider. Check here:
https://www-01.ibm.com/support/docview.wss?uid=isg3T1027163
For connection string samples, check here:
https://www.connectionstrings.com/as-400/
Also, check out the redbook for code examples and getting started.
http://www.redbooks.ibm.com/redbooks/pdfs/sg246440.pdf

Following is what I did to resolve the issue.
Installed the IBM i Access for Windows. Not free
Referred the following dlls in the project
IBM.Data.DB2.iSeries.dll
Interop.cwbx.dll (If Data Queue used)
Interop.AD400.dll (If Data Queue used)
Data Access
using (iDB2Command command = new iDB2Command())
{
command.Connection = (iDB2Connection)_connection;
command.CommandType = CommandType.Text;
command.Parameters.AddWithValue(Constants.ParamInterfaceTransactionNo, 1);
command.CommandText = dynamicInsertString;
command.ExecuteScalar();
}
Connection String
<add name="InterfaceConnection"
connectionString="Data Source=myserver.mycompany.com;User ID=idbname;Password=mypassxxx;
Default Collection=ASIPTA;Naming=System"/>
UPDATE
i Access for Windows on operating systems beyond Windows 8.1 may not be supported. Try the replacement product IBM i Access Client Solutions
IBM i Access Client Solutions

As mentioned in other answers, if you have the IBM i Access client already installed, you can use the IBM.Data.DB2.iSeries package.
If you don't have the IBM i Access software, you can leverage JTOpen and use the Java drivers. You'll need the nuget package JT400.78 which will pull in the IKVM Runtime.
In my case I needed to query a DB2 database on an AS400 and output a DataTable. I found several hints and small snippets of code but nothing comprehensive so I wanted to share what I was able to build up in case it helps someone else:
using com.ibm.as400.access;
using java.sql;
var sql = "SELECT * FROM FOO WITH UR";
DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
Connection conn = DriverManager.getConnection(
"jdbc:as400:" + ServerName + ";prompt=false", UserName, Password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData md = rs.getMetaData();
int ct = md.getColumnCount();
DataTable dt = new DataTable();
for(int i=1; i<=ct; i++)
dt.Columns.Add(md.getColumnName(i));
while (rs.next())
{
var dr = dt.NewRow();
for (int i = 1; i <= ct; i++)
dr[i - 1] = rs.getObject(i);
dt.Rows.Add(dr);
}
rs.close();
The conversion from RecordSet to DataTable is a little clunky and gave me bad flashbacks to my VBScript days. Performance likely isn't blinding fast, but it works.

Extremely old question - but this is still relevant. I needed to query our AS/400 using .NET but none of the answers above worked and so I ended up creating my own method using OleDb:
public DataSet query_iseries(string datasource, string query, string[] parameterName, string[] parameterValue)
{
try
{
// Open a new stream connection to the iSeries
using (var iseries_connection = new OleDbConnection(datasource))
{
// Create a new command
OleDbCommand command = new OleDbCommand(query, iseries_connection);
// Bind parameters to command query
if (parameterName.Count() >= 1)
{
for (int i = 0; i < parameterName.Count(); i++)
{
command.Parameters.AddWithValue("#" + parameterName[i], parameterValue[i]);
}
}
// Open the connection
iseries_connection.Open();
// Create a DataSet to hold the data
DataSet iseries_data = new DataSet();
// Create a data adapter to hold results of the executed command
using (OleDbDataAdapter data_adapter = new OleDbDataAdapter(command))
{
// Fill the data set with the results of the data adapter
data_adapter.Fill(iseries_data);
}
return iseries_data;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
And you would use it like so:
DataSet results = query_iseries("YOUR DATA SOURCE", "YOUR SQL QUERY", new string[] { "param_one", "param_two" }, new string[] { "param_one_value", "param_two_value"});
It returns a DataSet of the results returned. If anyone needs/wants a method for inserting/updating values within the IBM AS/400, leave a comment and I'll share...

I'm using this code and work very good for me!
Try
Dim sqltxt As String = "SELECT * FROM mplib.pfcarfib where LOTEF=" & My.Settings.loteproceso
dt1 = New DataTable
Dim ConAS400 As New OleDb.OleDbConnection
ConAS400.ConnectionString = "Provider=IBMDA400;" & _
"Data Source=192.168.100.100;" & _
"User ID=" & My.Settings.usuario & ";" & _
"Password=" & My.Settings.contrasena
Dim CmdAS400 As New OleDb.OleDbCommand(sqltxt, ConAS400)
Dim sqlAS400 As New OleDb.OleDbDataAdapter
sqlAS400.SelectCommand = CmdAS400
ConAS400.Open()
sqlAS400.Fill(dt1)
grid_detalle.DataSource = dt1
grid_detalle.DataMember = dt1.TableName
Catch ex As Exception
DevExpress.XtraEditors.XtraMessageBox.Show("Comunicación Con El AS400 No Establecida, Notifique a Informatica..", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Me.Close()
End Try

I recently found the ADO.Net driver available on NuGet. I have the iSeries client access installed on my PC, so I can't say if it works as a standalone, but it does connect. Theonly problem is I can't actually see any tables or procedures. I think there may be a schema or library or something I still haven't gotten down to. I will post if I find the answer. Meanwhile I can still get to the server and write most of my code with the NuGet adapter.

Check out http://asna.com/us/ as they have some development tools working with SQL and the AS400.

Related

connect to tableau postgresql in C#

I want to connect to the tableau PostgreSQL server from my .Net framework to list all the reports and datasources published in the tableau server.
For doing this, I have done the following steps.
Added the npgsql.dll reference that i downloaded online
Added the below two namespaces in my class file
using NpgsqlTypes;
using Npgsql;
I added the connection sting as follows
I also tried with modifying the connection string with port value and renaming the DataSource to Server, Initial catalog to Database and provider Name to Npgsqll
My Method is as follows:
public DataTable getAllDataSourceNames()
{
DataTable dataSourceNames = new DataTable();
NpgsqlConnection conServer = new NpgsqlConnection(conString);
conServer.Open();
string command = #"select * from datasources";
NpgsqlDataAdapter sqlcmd = new NpgsqlDataAdapter(command,conServer);
sqlcmd.Fill(dataSourceNames);
return dataSourceNames;
}`
No error. I can build and run successfully the other links in the website. But cannot cannot establish connection to my postgresql server.
Any idea of how to establish the connection?
Working with Postgres Connection in c#:
private DataSet ds = new DataSet();
private DataTable dt = new DataTable();
public Form1()
{
InitializeComponent();
}
private void llOpenConnAndSelect_LinkClicked(object sender,
LinkLabelLinkClickedEventArgs e)
{
try
{
// PostgeSQL-style connection string
string connstring = String.Format("Server={0};Port={1};" +
"User Id={2};Password={3};Database={4};",
tbHost.Text, tbPort.Text, tbUser.Text,
tbPass.Text, tbDataBaseName.Text );
// Making connection with Npgsql provider
NpgsqlConnection conn = new NpgsqlConnection(connstring);
conn.Open();
// quite complex sql statement
string sql = "SELECT * FROM simple_table";
// data adapter making request from our connection
NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conn);
// i always reset DataSet before i do
// something with it.... i don't know why :-)
ds.Reset();
// filling DataSet with result from NpgsqlDataAdapter
da.Fill(ds);
// since it C# DataSet can handle multiple tables, we will select first
dt = ds.Tables[0];
// connect grid to DataTable
dataGridView1.DataSource = dt;
// since we only showing the result we don't need connection anymore
conn.Close();
}
catch (Exception msg)
{
// something went wrong, and you wanna know why
MessageBox.Show(msg.ToString());
throw;
}
}
The following link may help you: Using PostgreSQL in your C# .NET application
Short answer -- no, not sure what's wrong. Your code doesn't raise any alarm bells.
Somewhat related, and it may help: I'm a big fan of the Connection StringBuilder with Npgsql. Here is a brief example:
NpgsqlConnectionStringBuilder sb = new NpgsqlConnectionStringBuilder();
sb.ApplicationName = "Tableau " + Environment.GetEvironmentVariable("USERNAME");
sb.Host = "1.2.3.4";
sb.Port = 5432;
sb.Username = "foo";
sb.Password = "bar";
sb.Database = "postgres";
sb.Pooling = false;
sb.Timeout = 120;
conServer = new NpgsqlConnection(sb.ToString());
It demistifies all of this and makes injecting parameters easy. I highly recommend you add the ApplicationName property so that when you are monitoring sessions, you will know who is who.

No read permission on MSysObject error

I am trying to connect to an MS Access database (.mdb) through OleDb. My query is
SELECT * FROM ListQueries
which fetches me the error
SQL Execution Error.
Executed SQL Statement: SELECT * FROM ListQueries
Error Source: Microsoft JET Database Engine
Error Message: Records cannot be read; No read permission on 'MSysObjects'.
Then I tried this answer, but it did not help. Then I saw another answer says to do this.
strDdl = "GRANT SELECT ON MSysObjects TO Admin;"
CurrentProject.Connection.Execute strDdl
I do not know how to implement that in my web project. Was writing something like this as per this suggestion by #HansUp
Alternatively, it should work from c# if you run it from an OleDb connection to the Access db
The code is,
OleDbConnection con;
using (con = new OleDbConnection(Connection.connectionString()))
{
con.Open();
using (var com = new OleDbCommand("GRANT SELECT ON MSysObjects TO Admin", con))
{
com.ExecuteNonQuery();
}
using (var com = new OleDbCommand("Select * from ListQueries", con))
{
using (var dr = com.ExecuteReader())
{
while (dr.Read())
{
qryList.Add(SQLReaderExtensions.SafeGetString(dr, "Name"));
}
dr.Close();
}
}
con.Close();
}
The first com.ExecuteNonQuery() gives me this error.
Cannot open the Microsoft Jet engine workgroup information file.
I would really like to know how to grant permission for an OleDb call to work. Any suggestions will be wonderful
P.S: BTW, I am using MS Access 2010.
I strongly suggest that you do not use MS Access system objects. There are other and better ways to get the information.
You have a choice of ADO and DAO. Which would you prefer? Note that in ADO there is a difference between action (adSchemaProcedures) and select queries (adSchemaViews).
For example,
public static List<string> GetAllQueriesFromDataBase()
{
var queries = new List<string>();
using (var con = new OleDbConnection(Connection.connectionString()))
{
con.Open();
var dt = con.GetSchema("Views");
queries = dt.AsEnumerable().Select(dr => dr.Field<string>("TABLE_NAME")).ToList();
}
return queries;
}

Connect to a database not created yet?

How do I create a SQL Compact Edition database? I have tried to figure it out, searched the internet and I cant find it (but then again, how do you search for this?!). Here is my code so far:
checkPasswordsMatch();
SqlCEConnection myconn = new SqlCEConnection();
SqlCeCommand myCommand = new SqlCeCommand(
#"CREATE DATABASE ""pwdb.sdf"" DATABASEPASSWORD '" + textBox1.Text + "'");
myCommand.ExecuteNonQuery();
What do I put on the connection part? I dont understand.
UPDATE: I decided to create a database to incorporate with the application, and simply check if there was a value (admin Password) dedicated to the record Master.
Here is my new code:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SqlCeConnection myconn = new SqlCeConnection("Data Source = pwdb.sdf;");
SqlCeCommand checkpass = new SqlCeCommand("SELECT * from PW WHERE Name = Master;",myconn);
try
{
myconn.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
if (checkpass.ExecuteNonQuery() != null)
{
Application.Run(new enterMasterPassword());
}
else
Application.Run(new mainPassSet());
The problem is, when i execute this now, i get:
An unhandled exception of type 'System.Data.SqlServerCe.SqlCeException' occurred in System.Data.SqlServerCe.dll
Any ideas anyone??
Try using the SqlCeEngine class. With that class you can create a new database:
using (SqlCeEngine engine = new SqlCeEngine())
{
engine.LocalConnectionString = yourConnectionString;
engine.CreateDatabase();
}
Since you likely only want to create the database once you may not want to do it in your code.
A couple suggestions:
1) if you're using Visual Studio you can open the Server Explorer (Under menu View->Server Explorer) and create it there.
2) Use one of the free SQL managers like linkpad or powershell + sqlcmd (there are others)
3) or... Don't know what data model you are using but EntityFramework with "code first" will create the database for you automatically based on your connection string and how you name your data context. Since you are using the sdf tag, maybe you are using EF...

access list in sharepoint 2007 using c#

I'm looking to compile data from a few diffrent custome lists in sharepoint 2007
Its a hosted sharepoint site so I don't have access to the machine backend.
Is there any example code to access the sharepoint site using c#?
here is my code thus far (i get the error Cannot connect to the Sharepoint site ''. Try again later.)
DataSet dt = new DataSet();
string query = "SELECT * FROM list";
string site = "http://sp.markonsolutions.com/Lists/Security/";
string list = "35E70EO4-6072-4T55-B741-4B75D5F3E397"; //security db
string myConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=2;RetrieveIds=Yes; DATABASE="+site+";LIST={"+list+"};";
OleDbConnection myConnection = new OleDbConnection();
myConnection.ConnectionString = myConnectionString;
OleDbCommand myAccessCommand = new OleDbCommand(query,myConnection);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(myAccessCommand);
myConnection.Open();
myDataAdapter.Fill(dt);
//execute queries, etc
myConnection.Close();
If you can't deploy code on the SharePoint machine, then you pretty much have to use the web services.
The lists web service is what you're after.
It will be located on http://yousharepointsite.com/_vti_bin/Lists.asmx and should be open by default. Note that if your site is configured with FBA, you will have to use the _vti_bin/Authentication.asmx to log in before you query lists.asmx.
Here is an article that gives all the information you need :
http://sharepointmagazine.net/articles/writing-caml-queries-for-retrieving-list-items-from-a-sharepoint-list
For the reasons mentioned above, skip the part on using the object model to query SharePoint lists and go directly to Retrieving list items with CAML using the SharePoint web services.
The article is pretty complete, so I think you should be OK with that.
As per your edit, I don't think that you can create a connection to your remote site like that. You can't query SharePoint with SQL like that, you really need to use CAML...
Once you've added the reference to the web service :
ListService listsClient = new ListService.Lists();
listsClient.Url = #"http://sp.markonsolutions.com/" + #"/_vti_bin/lists.asmx";
listsClient.Credentials = System.Net.CredentialCache.DefaultCredentials;
listsClient.GetListItems(...);
Read more on the GetListItems here
Like I said, you need to use the web services. You are heading towards a dead end if you are trying to create connection like that to query the database directly. It is not recommended.
Not sure if what you try to do is possible unless you use an ado.net connector for SharePoint, have a look at http://www.bendsoft.com/net-sharepoint-connector/
It enables you to talk to SharePoint lists as if they where ordinary sql-tables
In example to insert some data
public void SharePointConnectionExample1()
{
using (SharePointConnection connection = new SharePointConnection(#"
Server=mysharepointserver.com;
Database=mysite/subsite
User=spuser;
Password=******;
Authentication=Ntlm;
TimeOut=10;
StrictMode=True;
RecursiveMode=RecursiveAll;
DefaultLimit=1000;
CacheTimeout=5"))
{
connection.Open();
using (SharePointCommand command = new SharePointCommand("UPDATE `mytable` SET `mycolumn` = 'hello world'", connection))
{
command.ExecuteNonQuery();
}
}
}
Or to select list data to a DataTable
string query = "SELECT * FROM list";
conn = new SharePointConnection(connectionString);
SharePointDataAdapter adapter = new SharePointDataAdapter(query, conn);
DataTable dt = new DataTable();
adapter.Fill(dt);
Or using a helper method to fill a DataGrid
string query = "Select * from mylist.viewname";
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);

Querying remote MySql server

I think I have a straight forward question. I'm writing a system that allows users from company A to single sign on to the system and for this I go back to the central database of users at company A and validate the user credentials passed to me.
Currently my implementation involves building up my query using a stringbuilder and then passing the string as command text. My question is; is there a nicer way of doing this. below is my code;
public User LoginSSO(string UserName, Int32 sectorCode)
{
using (OdbcConnection con = new OdbcConnection(ConfigurationManager.ConnectionStrings["ComapnyA"].ConnectionString))
{
con.Open();
StringBuilder sb = new StringBuilder();
sb.AppendLine("Select mx.Id, mx.UserName, mx.firstname,mx.surname,mx.sectorCode,");
sb.AppendLine("mx.deleteFlag, dn.sectorGroupCode, dn.region, dn.district");
sb.AppendLine("from users mx");
sb.AppendLine("Inner Join sector dn on dn.sectorCode = mx.sectorCode");
sb.AppendLine("Where (mx.UserName = '{0}')");
string commandText = string.Format(sb.ToString(), UserName, sectorCode);
using (OdbcCommand comm = new OdbcCommand(commandText, con))
{
using (OdbcDataReader reader = comm.ExecuteReader())
{
if (reader.Read())
{
User user = new User();
user.Id = Convert.ToInt32(reader["Id"]);
user.Username = Convert.ToString(reader["UserName"]);
user.Firstname = Convert.ToString(reader["firstname"]);
user.Surname = Convert.ToString(reader["surname"]);
_dealerGroupCode = Convert.ToString(reader["sectorGroupCode"]);
_region = Convert.ToInt32(reader["region"]);
_district = Convert.ToInt32(reader["district"]);
_dealerCode = dealerCode;
_accessLevel = AccessLevel.Sector;
return user;
}
}
}
}
return null;
}
I don't like the fact that I am building up my sql which is ultimately a static script. Please note that I can't manipulate the remote server in any way or add any stored procedures to it. For the rest of the app I have been using LINQ but I'm assuming that isn't an option.
This is the most low-level way of querying a database with ADO.NET. Open connection, send command, read out results. You should however use parametrized queries instead of String.Format, since that will open up your program to SQL injection. Just consider what would happen if UserName has a ' character in it. The following would be much better:
string sql = #"Select mx.Id, mx.UserName, mx.firstname, mx.surname,
mx.sectorCode, mx.deleteFlag, dn.sectorGroupCode,
dn.region, dn.district
From users mx
Inner Join sector dn on dn.sectorCode = mx.sectorCode
Where (mx.UserName = ?)";
var command = new OleDbCommand(sql);
command.Parameters.AddWithValue(0, UserName);
If you want a higher level interface, look into DataSets/DataAdapters. They aren't as fancy as LINQ, but they'll give you an easy fill/update, and work with any database adapter. If you're using Visual Studio, you even get a visual designer that can generate Typed Datasets in drag-and-drop fashion that'll give you strong-typed accessors for all your data.
You might also want to look into the native MySql connector classes, instead of using ODBC.
You can use ‘sp_addlinkedserver’ system store procedure to link to the remote server server and then fire a query. following is the sample command.:
EXEC sp_addlinkedserver
#server = ‘SourceServer’
, #Srvproduct = ”
, #Provider = ‘SQLNCLI’
, #datasrc = ‘Remote SQL Server instance name’
I suggest you to please refer following link to know about how to run sql query on remote server http://ashishkhandelwal.arkutil.com/sql-server/sql-query-to-the-remote-sql-server/

Categories

Resources