Can DB2 DDL be generated using the IBM.Data.Db2 library - db2

I'm new to Db2 and need to generate DDL for an existing table but don't have access to any tools. Is it possible to do this through the IBM.Data.DB2 library? I can get a datareader but only the field name is available. I work in a very restrictive environment hence the no tools statement. I don't know what operating system is used on the server. I'm a c#\vb.net developer and can execute commands of type text and stored procedures; however, creating stored procedures is very limited. I've done this sort of thing with Sql's SMO library but am not well versed with IBM.Data.DB2.

using (DB2Command dB2Command = new DB2Command($"SELECT * FROM {database}.{tableName}", dB2Connection))
{
dB2Command.CommandType = System.Data.CommandType.Text;
using (DB2DataReader dB2DataReader = dB2Command.ExecuteReader())
{
DataTable dataTable = dB2DataReader.GetSchemaTable();
foreach(DataRow dataRow in dataTable.Rows)
{
Console.WriteLine($"ColumnName: {dataRow.Field<string>("ColumnName")}\nColumnSize: {dataRow.Field<int>("ColumnSize").ToString()}\nNumericPrecision: { dataRow.Field<Int16>("NumericPrecision").ToString()}\nNumericScale: { dataRow.Field<Int16>("NumericScale").ToString()}\nDataType: {dataRow.Field<DbType>("ProviderType").ToString()}");
Console.WriteLine("");
}
}
}

Related

EntityFrameworkCore: How to initialize a Database and seed it the first time user uses an application

I have build a project using Microsoft Visual Studio 2015 and EntityFrameworkCore.
I have seed manually a couple of dummy data and I was developing my solution. Now, I want to deploy the in the server, but I get the problem that by starting the application the first time, it crash since it does not find a data base and data.
I have googled and I find the solution for Visual Studio 2013 and previous using the CreateDatabaseIfNotExists class that need the package: System.Data.Entity
(http://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx), however, such classes and packages do not exist in EntityFrameworkCore.
How does I create and populate a database with at least one row if user is using my application by the first time in EntityFrameworkCore?
or which is the equivalent to System.Data.Entity in Entity Framework Core?
Rowan Miller says that ApplyMigrations is enough to create database (if not exist) and apply all (nesessary) migrations.
Create method like this:
public void CreateDbAndSampleData(IServiceProvider applicationServices)
{
using (var serviceScope = applicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
using (var db = serviceProvider.GetService<ApplicationDbContext>())
{
// This will [try to] create database
// and apply all necessary migrations
db.Database.AsRelational().ApplyMigrations();
// then you can check for existing data and modify something
var admin = db.Users.Where(x => x.Name == "Superadmin").FirstOrDefault();
if (admin == null)
{
db.Users.Add(new User {...});
db.SaveChanges();
}
}
}
}
And call it from your Startup.cs, at end of Configure method:
CreateDbAndSampleData(app.ApplicationServices);
This code will run on every app startup, so you need to be accurate and do not overwrite any non-critical data changes (like changing Users's comment etc)
You can use MusicStore app as a sample: Startup.cs and SampleData.cs

Using JDBC to work with an Access database containing Unicode (Punjabi, Hindi) data and table/column names

My Access database has a table with a column that contains text in Punjabi. I am trying to work with that database from Java (NetBeans) using JDBC.
My code is :
private void b1ActionPerformed(java.awt.event.ActionEvent evt)
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=" + "D:\\PP.accdb";
Connection conn = DriverManager.getConnection(url);
System.out.println("Connection Successful");
Statement stmt = conn.createStatement();
stmt.execute("select * from Emp");
ResultSet rs = stmt.getResultSet();
if (rs != null)
{
String s1,s2;
s1=" ";
s2=" ";
while ( rs.next() )
{
JOptionPane.showMessageDialog(null ,rs.getString(2), "Output" ,JOptionPane.INFORMATION_MESSAGE );
}
}
stmt.close();
conn.close();
}
catch (Exception err) { System.out.println("ERROR: " + err); }
}
UCanAccess version 3.x, released in August 2015, now supports Unicode characters in table and column names. Note that such names need to be enclosed in square brackets, at least for UCanAccess v3.0.0, for example:
sql = "SELECT [रंग], inEnglish FROM hindi";
(Original Answer)
If, as stated in your comment to the question, you have an Access database with table and column names in Hindi or Punjabi then the two most common "direct" approaches for working with an Access database from Java won't work for you:
(1) The JDBC-ODBC Bridge
This is what you have been trying to use. Unfortunately, the JDBC-ODBC Bridge has never worked properly with the Access ODBC driver when the database contains Unicode text that includes characters above code point U+007F. This is true for both text data and table/column names. Also, the JDBC-ODBC Bridge is obsolete: it has been removed from Java 8 and is not supported. So, this option is a dead-end.
(2) UCanAccess
UCanAccess can successfully read/write Unicode text data, but the current (2.x) version cannot work with metadata (table/column names) containing Unicode characters above code point U+007F. Support for those characters in table/column names is planned for the next major release of UCanAccess (3.x), but no timeframe for such a release has been announced.
Other options:
Depending on the constraints under which you need to operate, you might consider one or more of the following workarounds.
You could move the data from the Access database into another database whose JDBC driver supports metadata in the Hindi and Punjabi languages.
You could build your application in C# instead of Java. (Visual Studio 2013 Community Edition is available for free.)
If you really must stick with Java and your data really must stay in an Access database then you could install Microsoft SQL Server Express Edition, create a "Linked Server" in SQL Server that points to the Access database (details here), then use the JDBC Driver for SQL Server to run queries against the Access database.

Manage Transactions on Business Layer

I want to use TransactionScope class in my business layer to manage database operation in data access layer.
Here is my sample code. When i execute it, it tries to enable the dtc. I want to do the operation without enable dtc.
I already checked https://entlib.codeplex.com/discussions/32592 article. It didn't work for me. I read many articles on this subject but none of them really touch enterprise library or i didn't see.
by the way, i am able to use TransactionScope using dotnet sql client and it works pretty well.
what would be the inside of SampleInsert() method?
Thanks,
Business Layer method:
public void SampleInsert()
{
using (TransactionScope scope = new TransactionScope())
{
Sample1DAL dal1 = new Sample1DAL(null);
Sample2DAL dal2 = new Sample2DAL(null);
Sample3DAL dal3 = new Sample3DAL(null);
dal1.SampleInsert();
dal2.SampleInsert();
dal3.SampleInsert();
scope.Complete();
}
}
Data Access Layer method:
//sampleInsert method structurally same for each 3 dal
public void SampleInsert()
{
Database database = DatabaseFactory.CreateDatabase(Utility.DATABASE_INFO); ;
using (DbConnection conn = database.CreateConnection())
{
conn.Open();
DbCommand cmd = database.GetStoredProcCommand("P_TEST_INS", "some value3");
database.ExecuteNonQuery(cmd);
}
}
Hi yes this will enable dtc because you are creating 3 DB connections within one TransactionScope . When more than one DB connection is created within same TransactionScope the local transaction escalate to Distributed Transaction and hence dtc will be enabled to manage Distributed Trnsactions.You will have to do it in a way that only one DB connection is created for entire TransactionScope. I hope this will give you an idea.
After research and waching query analyzer, I changed the SampleInsert() body as follows and it worked. The problem was as ethicallogics mentioned opening new connection each time i access the database.
public void SampleInsert()
{
Database database = DatabaseFactory.CreateDatabase(Utility.DATABASE_INFO);
using (DbCommand cmd = database.GetStoredProcCommand("P_TEST_INS", "some value1"))
{
database.ExecuteNonQuery(cmd);
}
}

How can I override SQL scripts generated by MigratorScriptingDecorator

Using Entity Framework 4.3.1 Code first, and Data Migrations.
I have written a utility to automatically generate the Migration scripts for a target database, using the MigratorScriptingDecorator.
However, sometimes when re-generating the target database from scratch, the generated script is invalid, in that it declares a variable with the same name twice.
The variable name is #var0.
This appears to happen when there are multiple migrations being applied, and when at least two result in a default constraint being dropped.
The problem occurs both when generating the script form code, and when using the Package Manager console command:
Update-Database -Script
Here are the offending snippets form the generated script:
DECLARE #var0 nvarchar(128)
SELECT #var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'SomeTableName')
and
DECLARE #var0 nvarchar(128)
SELECT #var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'SomeOtherTableName')
I would like to be able to override the point where it generates the SQL for each migration, and then add a "GO" statement so that each migration is in a separate batch, which would solve the problem.
Anyone have any ideas how to do this, or if I'm barking up the wrong tree then maybe you could suggest a better approach?
So with extensive use of ILSpy and some pointers in the answer to this question I found a way.
Details below fo those interested.
Problem
The SqlServerMigrationSqlGenerator is the class ultimately responsible for creating the SQL statements that get executed against the target database or scripted out when using the -Script switch in the Package Manager console or when using the MigratorScriptingDecorator.
Workings
Examining the Genearate method in the SqlServerMigrationSqlGenerator which is responsible for a DROP COLUMN, it looks like this:
protected virtual void Generate(DropColumnOperation dropColumnOperation)
{
RuntimeFailureMethods
.Requires(dropColumnOperation != null, null, "dropColumnOperation != null");
using (IndentedTextWriter indentedTextWriter =
SqlServerMigrationSqlGenerator.Writer())
{
string value = "#var" + this._variableCounter++;
indentedTextWriter.Write("DECLARE ");
indentedTextWriter.Write(value);
indentedTextWriter.WriteLine(" nvarchar(128)");
indentedTextWriter.Write("SELECT ");
indentedTextWriter.Write(value);
indentedTextWriter.WriteLine(" = name");
indentedTextWriter.WriteLine("FROM sys.default_constraints");
indentedTextWriter.Write("WHERE parent_object_id = object_id(N'");
indentedTextWriter.Write(dropColumnOperation.Table);
indentedTextWriter.WriteLine("')");
indentedTextWriter.Write("AND col_name(parent_object_id,
parent_column_id) = '");
indentedTextWriter.Write(dropColumnOperation.Name);
indentedTextWriter.WriteLine("';");
indentedTextWriter.Write("IF ");
indentedTextWriter.Write(value);
indentedTextWriter.WriteLine(" IS NOT NULL");
indentedTextWriter.Indent++;
indentedTextWriter.Write("EXECUTE('ALTER TABLE ");
indentedTextWriter.Write(this.Name(dropColumnOperation.Table));
indentedTextWriter.Write(" DROP CONSTRAINT ' + ");
indentedTextWriter.Write(value);
indentedTextWriter.WriteLine(")");
indentedTextWriter.Indent--;
indentedTextWriter.Write("ALTER TABLE ");
indentedTextWriter.Write(this.Name(dropColumnOperation.Table));
indentedTextWriter.Write(" DROP COLUMN ");
indentedTextWriter.Write(this.Quote(dropColumnOperation.Name));
this.Statement(indentedTextWriter);
}
}
You can see it keeps track of the variables names used, but this only appears to keep track within a batch, i.e. a single migration. So if a migratin contains more than one DROP COLUM the above works fine, but if there are two migrations which result in a DROP COLUMN being generated then the _variableCounter variable is reset.
No problems are experienced when not generating a script, as each statement is executed immediately against the database (I checked using SQL Profiler).
If you generate a SQL script and want to run it as-is though you have a problem.
Solution
I created a new BatchSqlServerMigrationSqlGenerator inheriting from SqlServerMigrationSqlGenerator as follows (note you need using System.Data.Entity.Migrations.Sql;):
public class BatchSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate
(System.Data.Entity.Migrations.Model.DropColumnOperation dropColumnOperation)
{
base.Generate(dropColumnOperation);
Statement("GO");
}
}
Now to force the migrations to use your custom generator you have two options:
If you want it to be integrated into the Package Manager console, add the below line to your Configuration class:
SetSqlGenerator("System.Data.SqlClient",
new BatchSqlServerMigrationSqlGenerator());
If you're generating the script from code (like I was), add a similar line of code to where you have your Configuration assembly in code:
migrationsConfiguration.SetSqlGenerator(DataProviderInvariantName,
new BatchSqlServerMigrationSqlGenerator());

How do you configure Grails Datasources Plugin to have a schema search path on a datasource?

I'm using Postgres and also the Datasources plugin.
Rails has a property called schema_search_path. Is there an equivalent in Grails?
I have two schemas, hk and public in the database.
Where can I specify a search path for the schema or a specific schema name?
I was able to make this work using the syntax like the following on the individual class.
static mapping = {
table name:'he_stats_item_summary_keywords', schema:'he'
}
However, it would still be nice to know if there was an equivalent to the schema_search_path on the datasource.
Possible solution found at:
PostgreSQL Default Schema in DataSource
Add support the hibernate.default_schema property to the _DataSource.groovy file
development {
dataSource {
dbCreate = "update"
url = "jdbc:postgresql://localhost:5432/deploy"
hibernate.default_schema = "turnkey_dev"
dialect = org.hibernate.dialect.PostgreSQLDialect
}
}