C# SMO Select from Database - c#

I have been racking my brain trying to figure out how to execute a SELECT from Table using SMO in C# and returning that value to a string item.
I have seen multiple posts of how I can run a SQL script from within C# which is not what I want to do. Here is the code I have so far
public static void GetDealerInfo()
{
Server databaseServer = new Server(dbServer);
try
{
databaseServer.ConnectionContext.LoginSecure = dbSecure;
databaseServer.ConnectionContext.Login = dbUser;
databaseServer.ConnectionContext.Password = dbPass;
databaseServer.ConnectionContext.Connect();
sDealerName = databaseServer.ConnectionContext.ExecuteWithResults("USE DATABASE Select DataValue from TABLE where KEYField = 'DealershipName'").ToString();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
if (databaseServer.ConnectionContext.IsOpen)
{
databaseServer.ConnectionContext.Disconnect();
}
}
}
I also have a string called sDealerName which is where I want to pull, all I am getting is
sDealerName = System.Data.DataSet
Can anyone point me in the correct direction?
UPDATE:
Here is the code to get it going or at least what worked for me
try
{
databaseServer.ConnectionContext.LoginSecure = dbSecure;
databaseServer.ConnectionContext.Login = dbUser;
databaseServer.ConnectionContext.Password = dbPass;
databaseServer.ConnectionContext.DatabaseName = dbDatabase;
databaseServer.ConnectionContext.Connect();
DataSet dsName = databaseServer.ConnectionContext.ExecuteWithResults("Select DataValue from ABSetup where KEYField = 'DealershipName'");
sDealerName = dsName.Tables[0].Rows[0][0].ToString();
DataSet dsNum = databaseServer.ConnectionContext.ExecuteWithResults("Select DataValue from ABSetup where KEYField = 'ABOfficeCID'");
sDealerNumber = dsNum.Tables[0].Rows[0][0].ToString();
}

Change your code to:
DataSet ds = databaseServer.ConnectionContext.ExecuteWithResults("Select DataValue from TABLE where KEYField = 'DealershipName'");
The "USE DATABASE;", first, you may not need it. Second it, if you mean "USE MyDatabaseName;" , try it with a semi colon after the name.
More important to your question : then do a
Console.Writeline (ds.GetXml );
You'll then "see" the DataSet, the DataTable, the row inside the DataTable from which to "pluck" your scalar value.
string value = string.Empty;
if(null!=ds) {
if(null!=ds.Tables) {
if(ds.Tables.Count > 0) {
if(null!=ds.Tables[0].Rows) {
if(ds.Tables[0].Rows.Count > 0) {
if(null!=ds.Tables[0].Rows[0].Columns){
if(ds.Tables[0].Rows[0].Columns.Count > 0)
{
value = ds.Tables[0].Rows[0].Columns[0].Value;
}}}}}}}
"Count" may be "Length", I'm going from memory.
My code is untested from memory, so take it with a grain of salt.

You're calling ToString() on the object instance which is why you're getting the fullly qualified type name.
The value you're looking for will be inside a DataTable object within the DataSet. Run you're code again and break on the sDealerName line. Then using the magnifying glass tool click on that to open the dataset viewer and you'll be able to figure the rest out from there.

Related

Use of unassigned local variable - but I know that by the time the program reaches it, it will be assigned

So, I have this section of code:
void Readfile()
{
using (reader = new StreamReader(file))
{
string line = "";
DataTable table;
// Search for relevant "tables" in the file
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith("!"))
{
table = CreateDataTable(reader, line);
}
else
{
AddToTable(table); // Error: "Unassigned local variable"
}
}
}
}
DataTable CreateDataTable(StreamReader reader, string line)
{
if (line.Contains("!CUST"))
{
DataTable custTable = new DataTable();
custTable.TableName = "Customer";
string[] columns = line.Split(Convert.ToChar(9));
foreach (string s in columns)
{
custTable.Columns.Add(s);
}
return custTable;
}
return null;
}
The file this program is reading from will always be in this format:
!Line1
Line2
Line3
!Line4
[etc...]
So I know that this code is sound, in terms of "flow". It will always Create the Table first, before it adds to it. However, the way I have structured the code clearly doesn't work.
My original idea was that if I did create the DataTable before hand, (I.e. DataTable table = new DataTable();) then there would be an empty table floating around.
How should this be written?
You know, but not a compiler, so initialize it with null:
DataTable table = null;
you are getting lines from a file. which can be any file. (
if it is going in production and user changes that file - even you as programmer will not be sure that first line will starts with !)
Initially you have kept table unassigned and
here on this line,
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith("!"))
{
table = CreateDataTable(reader, line);
}
else
{
AddToTable(table); // Error: "Unassigned local variable"
}
}
you are either creating a table or calling AddToTable method passing table into that.
you know that file is having such data that first line of file will always starts with "!" , but compiler cannot be sure with that fact at compile time.
So as there are two cases in while loop : if and else. there are equal chances that flow will either go in if or in else.
So compiler will always get worried that at first iteration if flow goes in else part, by that time table will not be assigned to any value (not even null). So it generated compile time error.
to avoid such error as Backs suggested, initailize table will null (which will be the best solution)
DataTable table = null;
and when you are doing so, for the sake of being in safe side, you should check for table is not null in AddToTable method at first line.
void AddToTable(DataTable table)
{
if(table != null)
{
//your logic
}
}

SSIS Script Component Input0Buffer method no GetName()?

I am looking for a way to obtain my property names in a SSIS data flow task Script Component. I have been searching high and low only finding this. I have been trying to get this code to work, but I am too novice to understand what is happening here and I don't feel it is explained very well(no offense).
The source before this component is using a SQL query joining two tables. Inside the component, I would like to compare column to column. Then call an update method I created to use SqlConnection to perform the update.
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (Row.TableALastName != Row.TableBLastName)
// Call the update method if the last name did not match.
this.UpdateRecord("TableBLastName", Row.TableALastName.ToString(), Row.TableAAssociateId.ToString());
}
}
private void UpdateRecord(string columnName, string change, string associateId)
{
SqlConnection sqlConnection;
sqlConnection = new SqlConnection(this.Variables.Connection);
string updateQuery = "UPDATE [SomeDataBase].[dbo].[TableB] SET " + columnName + " = " + change + " WHERE [Associate_ID] = " + associateId;
using (SqlCommand cmd2 = new SqlCommand(updateQuery, sqlConnection))
{
sqlConnection.Open();
cmd2.ExecuteNonQuery();
sqlConnection.Close();
}
}
I would like to somehow get the PropertyName of Row.TableBLastName instead of having to hard code "TableBLastName" for each test I am doing, which will be a lot.
The problem is that the input buffer class does not have Property.GetName() This also means I can't add a method to the class to get the property names, as it is regenerated each run.
public Input0_ProcessInputRow(Input0Buffer Row)
{
Dictionary<string, List<string>> list = new Dictionary<string, List<string>>();
List<string> propertyList = new List<string>();
Type myType = typeof(Input0Buffer);
PropertyInfo[] allPropInfo = myType.GetProperties();
List<PropertyInfo> SqlPropInfo = allPropInfo.Where(x => !x.Name.Contains("AM_")).ToList();
// Loop through all the Sql Property Info so those without AM_
for (int i = 0; i < SqlPropInfo.Count(); i++)
{
List<string> group = new List<string>();
foreach (var propInfo in allPropInfo)
{
if (propInfo.Name.Contains(SqlPropInfo[i].Name))
{
// Group the values based on the property
// ex. All last names are grouped.
group.Add(propInfo.GetValue(Row, null).ToString());
}
}
// The Key is the Sql's Property Name.
list.Add(SqlPropInfo[i].Name, group);
}
foreach (var item in list)
{
// Do a check if there are two values in both SQL and Oracle.
if (item.Value.Count >= 2)
{
if (item.Value.Count() != item.Value.Distinct().Count())
{
// Duplicates exist do nothing.
}
else
{
// The values are different so update the value[0]. which is the SQL Value.
UpdateRecord(item.Key, item.Value[0], Row.AssociateId);
}
}
}
}
I separated the values from the two tables so there are two lists values from TableA and TableB. You can prefix the values from TableA with "AM_" or something distinct so you can use reflection to to get the properties with and without the prefix and find out which values belong to which table. Then I just loop through the properties and group the values with the properties from the target value (so those without the prefix "AM_") I then loop through the grouped list and compare the two values and if it's different, update TableA with the TableB values to match them
You are already in SSIS so I will propose using that (no matter how quick I usually jump to C# to solve problems)
This is a classic conditional split scenario:
Do your test then run the results into a SQL Update statement.

TableAdapter Query with optional WHERE paramerter

I am trying to create a TableAdapter query with an optional WHERE parameter.
This is my query:
SELECT Productos.Categoria, Productos.Subcategoria, Productos.Nombre,
Productos.Marca, Productos.Descripcion, Proveedores.Nombre AS Proveedor, Precios.Precio
FROM Precios, Productos, Proveedores
WHERE Precios.Producto_ID = Productos.ID AND Precios.Proveedor_ID =
Proveedores.ID AND Proveedores.Nombre = ?
I would like "Proveedores.Nombre = ?" to be optional or if ? = null or nothing, the query does not filter by Proveedores.Nombre
I have tried this:
(Proveedores.Nombre =#PNombre OR #PNombre = NULL)
But I have got an error:
Generated SELECT statement:
Error in WHERE clause near '#'.
Unable to parse the query text
Thank you very much for you help,
Regards
Andres
EDIT:
I ma in a windows form project. I am using a DataSource - DataSet linked to my access database. So to create FillBy() and GetData() I use a table-adapter which was automatically created when I inserted the DataSource to my WindowsForm.
This is the method created liked to the GetData() I am using:
public virtual DB_ProvProd2DataSet.ProductosDataTable GetDataByTodo(string Nombre) {
this.Adapter.SelectCommand = this.CommandCollection[5];
if ((Nombre == null)) {
throw new global::System.ArgumentNullException("Nombre");
}
else {
this.Adapter.SelectCommand.Parameters[0].Value = ((string)(Nombre));
}
DB_ProvProd2DataSet.ProductosDataTable dataTable = new DB_ProvProd2DataSet.ProductosDataTable();
this.Adapter.Fill(dataTable);
return dataTable;
}
Where this.CommandCollection[5] = the query and this.Adapter.SelectCommand.Parameters[0] is the input related to the '?' of the query.
I hope this helps!
Thanks!!!
Try assing it to a local variable:
string tmp= #PNombre
(Proveedores.Nomber==tmp || tmp == null)

c# CheckedListbox values

When I want to put the values in an array that are selected from a checkedlistbox. And then say:
messagebox.show(values[0]);
It's saying : System.Data.DataRowView
This is my current code:
string[] itemArr = new string[clbTables.CheckedItems.Count];
int counter = 0;
foreach (object item in this.clbTables.CheckedItems)
{
string temp = Convert.ToString(item);
itemArr[counter] = temp;
counter++;
}
MetroMessageBox.Show(this, itemArr[0].ToString());
What am I doing wrong here>?
EDIT ::
clbTables.DataSource = sqlDisplayContent.connectDataTable("SELECT ('Tafelnr: '+ CONVERT(varchar,tafelnr)+' Zitplaatsen: '+ CONVERT(varchar,zitPlaatsen)) AS dispValue,tafelnr FROM tabel");
clbTables.DisplayMember = "dispValue";
clbTables.ValueMember = "tafelnr";
class sqlDisplayContent
{
public static DataTable connectDataTable(string query)
{
SqlCommand comm= sqlCrud.returnSqlCommand(query);
SqlDataAdapter sda = new SqlDataAdapter(comm);
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
}
Thankss
The issue is that:
Convert.ToString(item);
will simply call the ToString() method of the object and store that, which in this case, is giving you the object's type. In this case, the type is System.Data.DataRowView. I suggest that you access the specific field in the row that you want by using:
((DataRowView)item).Row["FieldName"].ToString();
instead. You will want to replace "FieldName" with whatever the name of your column that you are wanting is. Additionally, you can use an int index instead of a string reference. Of course, if you need to access multiple fields, you can do this by simple string concatenation. The issue is that you need to access the specific field that you want. Not the entire row as you are currently on.
I hope this helps!
A couple references: DataRow, DataRowView
I suppose that your values[] array is not right. Please, refer to this example on MSDN.
https://msdn.microsoft.com/en-us/library/system.windows.forms.checkedlistbox.checkeditems(v=vs.110).aspx
string temp = ((CheckBox)item).Text;
You are passing in the object, not the object's text (which is what it seems you want the code to do).

hexadecimal value 0x00, is an invalid character: still encounter problem after replace \0 with ""

I have a problem with my code.
I used ASP.NET with Visual Studio 2010.
When i retrieve a data from database to a datatable in a webservice, some column give me a empty string data. This caused some problem with the XML retrieved and displayed. I try to put a Replace ("","") to replace \0\0\0. THis one can solve the problem. But now the problem is, the orginal data still shown in the XML. The original data is the one with \0\0.Before replace, the XML field is <VNDPNO></VNDPNO> and after replace become <VNDPNO />.
My question is, how to hide the original data.
I dont want the original data when i call it
It keep showing in the web browser in <diffgr:before>.
My source code is :
public DataTable GetItmSupDtls(string companycode, string itemCode,
string itemMajor, string itemMinor)
{
DataTable dsItmSupDtls;
//DataSet dsItmSupDtls = new DataSet();
IDBManager dbManager = new DBManager(DataProvider.SqlServer);
dbManager.ConnectionString = _connString;
try
{
dbManager.Open();
dbManager.CreateParameters(4);
dbManager.AddParameters(0, "#COYCDE", (object)companycode);
dbManager.AddParameters(1, "#ITMCDE", (object)itemCode);
dbManager.AddParameters(2, "#ITMMAJ", (object)itemMajor);
dbManager.AddParameters(3, "#ITMMIN", (object)itemMinor);
dsItmSupDtls = dbManager.ExecuteDataSet(
CommandType.StoredProcedure,
Utilities.DatabaseName("DBPurchase") + ".dbo.ITMSUPINFO_STKBALENQUIRY"
).Tables[0];
}
catch (Exception ex)
{
throw ex;
}
finally
{
dbManager.Dispose();
}
DataTable result = dsItmSupDtls.Clone();
foreach (DataRow dtRow in dsItmSupDtls.Rows)
{
dtRow["VNDPNO"] =
dtRow["VNDPNO"].ToString().Replace("\0", ""); //"A"; //
result.ImportRow(dtRow);
}
return result;
}
Kindly give me some comment and suggestion.
Many thanks..
The way your information is being transfered is through a diffgram. I think the history will come with it if you use ImportRow instead of InsertRow. Since InsertRow can be more expensive with a lot of rows you may want to only use ImportRow when the value contained a null.

Categories