Metro Application connects to SQL via WCF Service - Error - c#

I have created a new metro application for Windows 8.
My intention was to consume data from the WCF data service in the metro application. The WCF service should connect to a SQL server installed on the local machine.
I have set up an Interface for my service so I can pass parameters to the methods I want the WCF to execute and then return results back to the Metro Application afterwards.
I followed a few different tutorials online and had success, until...
A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or
was not accessible. Verify that the instance name is correct and that
SQL Server is configured to allow remote connections. (provider: Named
Pipes Provider, error: 40 - Could not open a connection to SQL Server)
I have a included the code from both the Login landing Page and the SQL configuration page. When the metro application launches, it runs a method to check if there is a connection. If no connection is found it displays the SQL configuration page.
The application launches. OnNavigate to the login form the CheckConnection() method returns true. But when I enter user details and press login I simply get an error on the following line of code in the async void Login() method on the Login Page
newCustomType = await dataServiceClientName.CheckLoginAsync(txtUsername.Text, txtPassword.Text);
If anyone understands why this error is displaying the help would be greatly appreciated.
I have included the relevant code (or what I can tell is relevant) below.
Thanks in advance :)
Code Snippets:
Abridged Service Interface
[ServiceContract]
public interface CTUServiceInterface
{
// TODO: Add your service operations here
//LoginForm
[OperationContract]
bool CheckConnection();
//SQL Config
[OperationContract]
bool UpdateConnectionDetails(string ConnectionString);
//LoginForm
[OperationContract]
LoginDetails CheckLogin(string Username, string Password);
//LoginForm Success
[OperationContract]
UserGlobalDetails GetActiveUserDetails(int UserKey);
}
[DataContract]
public class LoginDetails
{
bool loginSuccess = false;
string errorMessage = "";
int userKey = -1;
[DataMember]
public bool LoginSuccess
{
get { return loginSuccess; }
set { loginSuccess = value; }
}
[DataMember]
public string ErrorMessage
{
get { return errorMessage; }
set { errorMessage = value; }
}
[DataMember]
public int UserKey
{
get { return userKey; }
set { userKey = value; }
}
}
[DataContract]
public class UserGlobalDetails
{
string firstName = "";
string lastName = "";
int departmentKey = -1;
bool manager = false;
[DataMember]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
[DataMember]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
[DataMember]
public int DepartmentKey
{
get { return departmentKey; }
set { departmentKey = value; }
}
[DataMember]
public bool Manager
{
get { return manager; }
set { manager = value; }
}
}
Abridged Service Code
public class CTUService : CTUServiceInterface
{
private static SqlConnection localConnection = new SqlConnection("Data Source=PC-VIRTUAL;Initial Catalog=CarTraUnl;Integrated Security=True");
//LoginForm
public bool CheckConnection()
{
bool result = true;
try
{
localConnection.Open();
localConnection.Close();
}
catch(Exception ex)
{
result = false;
throw ex;
}
return result;
}
//SQL Config
public bool UpdateConnectionDetails(string ConnectionString)
{
localConnection = new SqlConnection(ConnectionString);
return CheckConnection();
}
//LoginForm
public LoginDetails CheckLogin(string Username, string Password)
{
//Initilize the LoginDetails Object to return with results
LoginDetails localDetails = new LoginDetails();
//Initilize the localDataTable to hold sql results
DataTable localDataTable = new DataTable("localDataTable");
//Setup a SqlDataAdapter and get info from the 'UserGlobal' Table
localConnection.Open();
SqlDataAdapter localDataAdapter = new SqlDataAdapter(
"SELECT [Password],[Key]" +
"FROM [CarTraUnl].[dbo].[UserGlobal]" +
"WHERE [Username] = '" + Username + "'"
, localConnection);
localConnection.Close();
//Fill localDataTable with information from the UserGlobal Table
localDataAdapter.Fill(localDataTable);
//Set loginStatus equal to the number of passwords found for the given username
int loginStatus = localDataTable.Rows.Count;
//If no passwords are found, there was no username like the given one
if (loginStatus == 0)
{
localDetails.ErrorMessage = "Invalid Username";
}
//If one password was found, check if it matches the given password
else if (loginStatus == 1 && localDataTable.Rows[0][0].ToString() == Password)
{
localDetails.LoginSuccess = true;
localDetails.ErrorMessage = "";
localDetails.UserKey = int.Parse(localDataTable.Rows[0][1].ToString());
}
//If one password is found, but it doesn't match show the error
else if (loginStatus == 1 && localDataTable.Rows[0][0].ToString() != Password)
{
localDetails.ErrorMessage = "Invalid Password";
}
//If multiple passwords are found, there are duplicate usernames
else if (loginStatus > 1)
{
localDetails.ErrorMessage = "Duplicate Usernames";
}
return localDetails;
}
//LoginForm Success
public UserGlobalDetails GetActiveUserDetails(int UserKey)
{
//Initilize UserGlobalDetails object to return later
UserGlobalDetails localUserGlobalDetails = new UserGlobalDetails();
//Initilize a DataTable to hold our sql results
DataTable localDataTable = new DataTable("localDataTable");
//Setup a SqlDataAdapter and get info from the 'UserGlobal' Table
SqlDataAdapter localDataAdapter = new SqlDataAdapter(
"SELECT [FirstName],[LastName],[DepartmentKey],[Manager]" +
"FROM [CarTraUnl].[dbo].[UserGlobal]" +
"WHERE [Key] = '" + UserKey + "'"
, localConnection);
//Fill localDataTable with information from the 'UserGlobal' Table
localDataAdapter.Fill(localDataTable);
//Configure the UserGlobalDetails object 'localUserGlobalDetails' with the retrived results
localUserGlobalDetails.FirstName = localDataTable.Rows[0][0].ToString();
localUserGlobalDetails.LastName = localDataTable.Rows[0][1].ToString();
localUserGlobalDetails.DepartmentKey = int.Parse(localDataTable.Rows[0][2].ToString());
localUserGlobalDetails.Manager = bool.Parse(localDataTable.Rows[0][3].ToString());
//return the results
return localUserGlobalDetails;
}
}
Login.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
lblError.Text = "";
}
private async void CheckConnection()
{
CTUServiceReference.CTUServiceInterfaceClient dataServiceClientName = new CTUServiceReference.CTUServiceInterfaceClient();
bool result = await dataServiceClientName.CheckConnectionAsync();
if (result == false)
{
this.Frame.Navigate(typeof(SqlConfig));
}
}
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
Login();
}
private async void Login()
{
btnLogin.IsEnabled = false;
CTUServiceReference.CTUServiceInterfaceClient dataServiceClientName = new CTUServiceReference.CTUServiceInterfaceClient();
CTUServiceReference.LoginDetails newCustomType = new CTUServiceReference.LoginDetails();
newCustomType = await dataServiceClientName.CheckLoginAsync(txtUsername.Text, txtPassword.Text);
CTUServiceReference.UserGlobalDetails currentActiveUserDetails = new CTUServiceReference.UserGlobalDetails();
currentActiveUserDetails = await dataServiceClientName.GetActiveUserDetailsAsync(newCustomType.UserKey);
//The globalSettings.cs file is not included, but it just holds persistent application data
globalSettings.currentUserKey = newCustomType.UserKey;
globalSettings.firstName = currentActiveUserDetails.FirstName;
globalSettings.lastName = currentActiveUserDetails.LastName;
globalSettings.departmentKey = currentActiveUserDetails.DepartmentKey;
globalSettings.manager = currentActiveUserDetails.Manager;
if (newCustomType.LoginSuccess)
{
//This page is where we go when login is successful
this.Frame.Navigate(typeof(FormSelector));
}
else
{
lblError.Text = newCustomType.ErrorMessage;
btnLogin.IsEnabled = true;
}
}
SQLConfig.xaml.cs
private void btnSqlConfigSave_Click(object sender, RoutedEventArgs e)
{
saveConfig();
}
private async void saveConfig()
{
btnSave.IsEnabled = false;
string connectionstring = "";
if (rbAutomatic.IsChecked == true)
{
//Integrated Secturity
connectionstring = "Data Source=" + txtServer.Text + ";Initial Catalog= " + txtDB.Text + ";Integrated Security=True";
}
else
{
//Standard Authentication with username and password
connectionstring = "Data Source=" + txtServer.Text + ";Initial Catalog= " + txtDB.Text + ";User Id=" + txtUser.Text + ";Password=" + txtPass.Text;
}
CTUServiceReference.CTUServiceInterfaceClient dataServiceClientName = new CTUServiceReference.CTUServiceInterfaceClient();
bool result = await dataServiceClientName.UpdateConnectionDetailsAsync(connectionstring);
if (result)
{
this.Frame.GoBack();
return;
}
else
{
lblError.Text = "Config error";
btnSave.IsEnabled = true;
}
}
Version Info
Visual Studio
Microsoft Visual Studio Ultimate 2012
Version 11.0.50727.1 RTMREL
Microsoft .NET Framework Version 4.5.50709
Installed Version: Ultimate
SQL Server
Microsoft SQL Server Management Studio - 11.0.2100.60
Microsoft Analysis Services Client Tools - 11.0.2100.60
Microsoft Data Access Components (MDAC) - 6.2.9200.16384
Microsoft MSXML - 3.0 6.0
Microsoft .NET Framework - 4.0.30319.18051
Operating System - 6.2.9200

This error could have several causes but it means what it means... being, your service cannot access to:
"Data Source=" + txtServer.Text + ";
This is most probably not a problem in your code, but an SQLServer configuration issue.
I suggest you try the connectionString in an ODBC call first to see if you can access it like this from local and remote.
it seems like your services tries to connect via named pipes check in the SQLServer Configuration Manager to see if the protocol is started for your specific instance.
Also try to enable the TCP/IP protocol and check that it listens on the right port (1433).
It could also be you are not targeting the "Named Instance". ie:
"Data Source=MYSERVER"
instead of
"Data Source=MYSERVER\MyInstance"
hope this helps!

Related

Adding/Removing SQLite database password programmatically

Trying to create functions to programmatically add a password to the sqlite database, and remove it - to get rid of the password when in debug.
I followed the steps of the best post explaining it (https://stackoverflow.com/a/1385690/6617804) and all the other sources that I found are using the same process.
What I am doing:
The connection strings:
private static string AuthoringDbFullPath = System.IO.Path.Combine(DataFolder, "Authoring.db");
private static string AuthoringConnectionStringWithPw = #"Data Source=" + AuthoringDbFullPath + "; Password=" + DbPassword +";";
private static string AuthoringConnectionStringWithoutPw = #"Data Source=" + AuthoringDbFullPath+";";
private static string AuthoringConnectionString = AuthoringConnectionStringWithPw;
The enable password function:
public static bool EnableDbPassword()
{
try
{
//The Connection must not open closed to set a password
Connection = new SQLiteConnection(AuthoringConnectionStringWithoutPw);
Connection.SetPassword(DbPassword);
Connection = new SQLiteConnection(AuthoringConnectionStringWithPw);
Connection.Open();
Connection.Close();
if (Connection != null && Connection?.State == System.Data.ConnectionState.Open)
{
Connection.SetPassword(DbPassword);
AuthoringConnectionString = AuthoringConnectionStringWithPw;
return true;
}
}
catch (Exception ex)
{
LogManager.LogException(ex);
}
return false;
}
The disable password function:
public static bool DisableDbPassword()
{
try
{
//if not connected, it does
if (Connection == null || Connection?.State != System.Data.ConnectionState.Open)
{
Connection = new SQLiteConnection(AuthoringConnectionStringWithPw);
Connection.Open();
}
Connection.Close();
Connection.Open();
if (Connection != null && Connection?.State == System.Data.ConnectionState.Open)
{
Connection.ChangePassword("");
AuthoringConnectionString = AuthoringConnectionStringWithoutPw;
return true;
}
}
catch (Exception ex)
{
LogManager.LogException(ex);
}
return false;
}
Two things happening:
After having add the password (with no apparent issue), I can still open the database in SQLiteStudio as if there were still no password:
When trying to disable after having enabled it, it raised a System.Data.SQLite.SqliteException exception when executing Connection.ChangePassword("");
System.Data.SQLite.SqliteException :
Message "file is not a database. not an error
How to create a simple architecture being able to add and remove a password on a SQLite database?

C# - "Connection must be valid and open" with multiple Queries and Methods | Connection not closed?

For many hours now I have lost it over this same error no matter what I change.
I'm trying to make a command line application that will retrieve info from a database based off of two argument inputs, the modname and the optional author. The queries are all handled in the jobs.cs file. The entry-point file calls the method beginJob() which gets the target modname and author (if specified) to query. What's different from the hundred or so other posts I've read here is that the first query issued works completely fine, and I'm sure to close the reader and connection. (Won't close connection every time in production, but I did here for debugging purposes). The next time I call the connection it results in this error.
System.InvalidOperationException: Connection must be valid and open.
at MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception)
at MySql.Data.MySqlClient.MySqlConnection.Throw(Exception ex)
at MySql.Data.MySqlClient.MySqlCommand.CheckState()
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
at vmcmod.Job.queryAuthor(String authorUID) in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 235
at vmcmod.Job.StartJob() in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 47
at vmcmod.Job.queryModAndAuthor(String modname, String author) in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 205
at vmcmod.Job.beginJob() in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 27
at vmcmod.VMCMOD.parseArgs() in F:\Projects\VisualStudio\VMC-MOD\vmcmod\vmcmod.cs:line 58
Some posts I've looked at but don't seem to help:
C# Mysql Connection must be valid and open
Connection must be valid and open error
C# Query: 'System.InvalidOperationException' | Additional information: Connection must be valid and open
C# Source Files (Please try and not cringe too hard, this is my first C# application):
jobs.cs [updated]
using MySql.Data.MySqlClient;
using System;
namespace vmcmod
{
class Job
{
public bool checkInput()
{
if (Global.currentJobTargetModname == "undefined")
{
Utils.consoleLog("The mod name is required.", 3);
return false;
}
else
{
return true;
}
}
public void beginJob()
{
string targetModname = Global.currentJobTargetModname.ToLower();
string targetModAuthor = Global.currentJobTargetAuthor.ToLower();
if (targetModAuthor != "undefined")
{
queryModAndAuthor(targetModname, targetModAuthor);
Utils.consoleLog("Job Call. (Author defined)", 4);
}
else
{
queryMod(targetModname);
Utils.consoleLog("Job Call. (Author undefined)", 4);
}
}
private void StartJob()
{
string author = null;
string targetModAuthor = Global.currentJobTargetAuthor.ToLower();
Utils.consoleLog("Mod exists.", 5);
if (targetModAuthor == "undefined")
{
author = "(None; First in row)";
}
else
{
queryAuthor(Global.queryResModAuthorID);
author = "'" + Global.queryResModAuthor + "' (UUID:" + Global.queryResModAuthorID + ") ";
}
var collaborators_obj = Newtonsoft.Json.Linq.JObject.Parse(Global.queryResModCollab);
var tags_obj = Newtonsoft.Json.Linq.JObject.Parse(Global.queryResModTags);
Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("MOD INSTALL SPECIFICATIONS:");
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine(" Mod Name: '" + Global.queryResModName + "'");
Console.Write(" Mod Author: " + author);
if (Global.queryResModAuthorVerified == true && targetModAuthor != "undefined")
{
Utils.consoleTag("*VERIFIED*", ConsoleColor.Green);
}
if (Global.queryResModAuthorVerified == false && targetModAuthor != "undefined")
{
Utils.consoleTag("*UNVERIFIED*", ConsoleColor.Red);
}
Console.Write("\n");
Console.WriteLine(" Mod Version: " + Global.queryResModVersion);
Console.WriteLine(" Installations: " + Global.queryResModInstalls);
Console.WriteLine(" Description:\n " + Global.queryResDescription);
Console.WriteLine(" Mod UUID: " + Global.queryResModUid);
if (Global.advInfo == true)
{
Console.WriteLine(" Rep. Entry #" + Global.queryResModID);
Console.WriteLine(" Mod Created On: " + Utils.UnixTimeStampToDateTime(Convert.ToDouble(Global.queryResDateCreated)));
Console.WriteLine(" Mod Last Modified On: " + Utils.UnixTimeStampToDateTime(Convert.ToDouble(Global.queryResDateLastModf)));
Console.WriteLine(" Tags: \n " + Convert.ToString(tags_obj["tags"]));
Console.WriteLine(" Collaborators: \n " + Convert.ToString(collaborators_obj["collaborators"]));
}
Utils.consoleSeparator();
bool user_response = Utils.consoleAskYN("Are you sure you want to install this mod?");
if (user_response == true)
{
queryGetModJSON(Global.queryResModUid);
Utils.consoleLog("JSON Data: "+Global.queryResModJSON,5);
//FileIO fio = new FileIO();
//fio.jsonToFiles(fio.jsonToArray(Global.queryResModJSON));
}
else
{
Utils.consoleSetKeyExit();
}
}
private void queryGetModJSON(string uuid)
{
var dbCon = new DBConnection();
if (dbCon.IsConnect() == false)
{
Utils.consoleLog("Unable to query repository or no results.", 3);
Utils.consoleSetKeyExit();
}
else
{
string q = "SELECT data_json FROM vmcmod_repository_data WHERE uid='" + uuid + "' LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
Utils.consoleLog("Mod data not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModJSON = reader.GetString(0);
}
reader.Close();
dbCon.Close();
}
}
}
private void queryMod(string modname)
{
var dbCon = new DBConnection();
if (dbCon.IsConnect() == false)
{
Utils.consoleLog("Unable to query repository or no results.", 3);
Utils.consoleSetKeyExit();
}
else
{
string q = "SELECT id,uid,author_id,mod_name,status,dependencies_json,description,mod_version,date_created,date_last_modified,collaborators,tags_json,installs FROM vmcmod_repository_info WHERE mod_name LIKE'" + modname + "' LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
Utils.consoleLog("Mod not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModInstalls = reader.GetInt32(12);
Global.queryResModTags = reader.GetString(11);
Global.queryResModCollab = reader.GetString(10);
Global.queryResDateLastModf = reader.GetInt32(9);
Global.queryResDateCreated = reader.GetInt32(8);
Global.queryResModVersion = reader.GetFloat(7);
Global.queryResDescription = reader.GetString(6);
Global.queryResModDependencies = reader.GetString(5);
Global.queryResModStatus = reader.GetInt16(4);
Global.queryResModName = reader.GetString(3);
Global.queryResModAuthorID = reader.GetString(2);
Global.queryResModUid = reader.GetString(1);
Global.queryResModID = Convert.ToInt32(reader.GetInt32(0));
}
reader.Close();
dbCon.Close();
StartJob();
}
}
}
private void queryModAndAuthor(string modname, string author)
{
var dbCon = new DBConnection();
if (dbCon.IsConnect() == false)
{
Utils.consoleLog("Unable to query repository or no results.", 3);
Utils.consoleSetKeyExit();
}
else
{
string q = "SELECT id,uid,author_id,mod_name,status,dependencies_json,description,mod_version,date_created,date_last_modified,collaborators,tags_json,installs FROM vmcmod_repository_info WHERE mod_name LIKE'" + modname + "' LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
Utils.consoleLog("Mod not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModInstalls = reader.GetInt32(12);
Global.queryResModTags = reader.GetString(11);
Global.queryResModCollab = reader.GetString(10);
Global.queryResDateLastModf = reader.GetInt32(9);
Global.queryResDateCreated = reader.GetInt32(8);
Global.queryResModVersion = reader.GetFloat(7);
Global.queryResDescription = reader.GetString(6);
Global.queryResModDependencies = reader.GetString(5);
Global.queryResModStatus = reader.GetInt16(4);
Global.queryResModName = reader.GetString(3);
Global.queryResModAuthorID = reader.GetString(2);
Global.queryResModUid = reader.GetString(1);
Global.queryResModID = Convert.ToInt32(reader.GetInt32(0));
}
reader.Close();
dbCon.Close();
StartJob();
}
}
}
private bool queryCheckAuthorExists(string author)
{
var dbCon = new DBConnection();
string q = "SELECT * FROM vmcmod_users WHERE username='"+author+ "' AND is_author=true LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (reader.HasRows == false)
{
Utils.consoleLog("Author not found.", 3);
reader.Close();
dbCon.Close();
return false;
}
else
{
Utils.consoleLog("Author found.", 4);
reader.Close();
dbCon.Close();
return true;
}
}
private void queryAuthor(string authorUID)
{
var dbCon = new DBConnection();
string q = "SELECT username,is_verified_user FROM vmcmod_users WHERE uid='" + authorUID + "' AND is_author=true LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (reader.HasRows == false)
{
Utils.consoleLog("Author not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModAuthor = reader.GetString(0);
Global.queryResModAuthorVerified = reader.GetBoolean(1);
}
Utils.consoleLog("Author found.", 4);
reader.Close();
dbCon.Close();
}
}
}
}
dbinterface.cs (this wasn't written by me, rather taken and edited from a post on stackoverflow, here) [updated]
using MySql.Data.MySqlClient;
using System;
namespace vmcmod
{
public class DBConnection
{
public DBConnection()
{
}
public string Password { get; set; }
private MySqlConnection connection = null;
public MySqlConnection Connection
{
get { return connection; }
}
public bool IsConnect()
{
bool result = true;
if (Connection == null)
{
string connString = "Server=...; Port=...; Database=...; Uid=...; Pwd=...;";
connection = new MySqlConnection(connString);
try
{
connection.Open();
Utils.consoleLog("Connected to repository.", 4);
result = true;
}
catch (Exception e)
{
Utils.consoleLog("Error occured while connecting to repository.", 3);
Utils.consoleLog("MySQL Exception: "+e,5);
result = false;
}
}
return result;
}
public void Close()
{
connection.Close();
connection = null;
}
}
}
global.cs (global variable storage)
using System;
namespace vmcmod
{
class Global
{
internal const float version = 0.1F;
internal static string currentJobWorld = "New World";
internal static string currentJobTargetModname = "undefined";
internal static string currentJobTargetAuthor = "undefined";
internal static string currentJobProfile = "default";
internal static int currentJobAccountPIN;
internal static bool verbose = false;
internal static bool debug = false;
internal static bool advInfo = false;
internal static bool queryResModAuthorVerified = false;
internal static string queryResModUid;
internal static string queryResModAuthorID;
internal static string queryResModAuthor;
internal static string queryResModName;
internal static string queryResModDependencies = "{\"dependencies\":[]}";
internal static int queryResModStatus;
internal static float queryResModVersion;
internal static string queryResDescription = "None provided.";
internal static int queryResDateCreated;
internal static int queryResDateLastModf;
internal static int queryResModID;
internal static string queryResModCollab = "{\"collaborators\":[]}";
internal static string queryResModTags = "{\"tags\":[]}";
internal static int queryResModInstalls;
internal static string queryResModJSON = "{}";
}
}
The quick and dirty solution would be to change:
public void Close()
{
connection.Close();
}
to:
public void Close()
{
connection.Close();
connection = null;
}
Also, remove this code:
private static DBConnection _instance = null;
public static DBConnection Instance()
{
if (_instance == null)
_instance = new DBConnection();
return _instance;
}
and rather than use DBConnection.Instance, just use new DBConnection();
And change:
public MySqlConnection Connection
{
get { return connection; }
}
to:
public MySqlConnection Connection
{
get {
IsConnect();
return connection; }
}
and change:
public bool IsConnect()
{
bool result = true;
if (Connection == null)
to:
public bool IsConnect()
{
bool result = true;
if (connection == null)
I see you are using singletne pattern for DBConnection this is not a good idea.
private static DBConnection _instance = null;
public static DBConnection Instance()
{
if (_instance == null)
_instance = new DBConnection();
return _instance;
}
You might want to check this answer out for more information: https://stackoverflow.com/a/814606/8143718
As per #mjwills' response, the DB interface script I'd swiped was quite funky and only allowed one instance at a time.
Working DB Interface
using MySql.Data.MySqlClient;
using System;
namespace vmcmod
{
public class DBConnection
{
public DBConnection()
{
}
public string Password { get; set; }
private MySqlConnection connection = null;
public MySqlConnection Connection
{
get
{
IsConnect();
return connection;
}
}
public bool IsConnect()
{
bool result = true;
if (connection == null)
{
string connString = "Server=...; Port=...; Database=...; Uid=...; Pwd=...;";
connection = new MySqlConnection(connString);
try
{
connection.Open();
Utils.consoleLog("Connected to repository.", 4);
result = true;
}
catch (Exception e)
{
Utils.consoleLog("Error occured while connecting to repository.", 3);
Utils.consoleLog("MySQL Exception: "+e,5);
result = false;
}
}
return result;
}
public void Close()
{
connection.Close();
connection = null;
}
}
}

Passing values between Windows form and a database

I faced a problem while trying to build a Windows form solution for a college assignment, and hope somebody can point out my mistake.
The solution is about a mobile shop. I have two classes, Apple and Android forms. I need to read the data in the database table, categorize the entries to either Android or Apple phones, and then display all phones in a list when the form loads.
I can successfully categorize phones, but when trying to read the entries, I always end up with the same entry twice in my list on the form, while the second entry doesn't appear at all.
I know I made a big stupid mistake while doing the connection but I can't find it!.
Here is my code:
public abstract class MobilePhone {
private Int32 phoneID;
private string operatingSystem;
private string make;
private string model;
public enum Condition { Poor, Fair, Good, Mint };
private Condition condition;
private decimal originalPrice;
private DateTime datePurchase;
private string description;
private clsDataConnection dbConnection;
//constructor
public MobilePhone(string make, string model, decimal originalPrice, DateTime datePurchase, Condition condition, string description) {
this.make = make;
this.model = model;
this.originalPrice = originalPrice;
this.datePurchase = datePurchase;
this.condition = condition;
this.description = description;
}
Not complete, but that's what is relevant:
public class ApplePhone : MobilePhone {
decimal ApproxValue;
public ApplePhone(string make, string model, decimal originalPrice, DateTime datePurchase, Condition condition, string description)
: base(make, model, originalPrice, datePurchase, condition, description) {
}
The Android class is the same but with different other functions.
class Shop {
clsDataConnection dbConnection;
const int NotAdded = -1; // invalid primary key
private string name;
private decimal ApproxValue;
private Int32 phoneID;
private string operatingSystem;
private string make;
private string model;
private MobilePhone.Condition condition;
private decimal originalPrice;
private DateTime datePurchase;
private string description;
Int32 Index;
private List<MobilePhone> phonesForSale;
//constructor
public Shop(string name) {
this.name = name;
}
MobilePhone phone;
public void SelectAll() {
dbConnection = new clsDataConnection();
dbConnection.Execute("SellectAllPhones");
}
public void FilterByOperatingSystem(string operatingSystem) {
dbConnection = new clsDataConnection();
dbConnection.AddParameter("#OperatingSystem", operatingSystem);
dbConnection.Execute("FilterByOperatingSystem");
}
public Int32 Count {
get {
//return the count of records
return dbConnection.Count;
}
}
public string DescribeCurrentPhone(int Index) {
Int32 phoneID;
string make;
string model;
MobilePhone.Condition condition;
decimal originalPrice;
DateTime datePurchase;
string description;
phoneID = Convert.ToInt32(phonesForSale[Index].PhoneID);
make = Convert.ToString(phonesForSale[Index].Make);
model = Convert.ToString(phonesForSale[Index].Model);
condition = phonesForSale[Index].GetCondition;
originalPrice = Convert.ToDecimal(phonesForSale[Index].OriginalPrice);
datePurchase = Convert.ToDateTime(phonesForSale[Index].DatePurchased);
description = Convert.ToString(phonesForSale[Index].Description);
//set up a new object of class list item
string listItemText = make + " " + "|" + " " + model + " " + "|" + " " + condition + " " + "|" + " " + "£" + Math.Round(originalPrice, 2) + " " + "|" + " " + datePurchase.ToShortDateString() + " " + "|" + " " + description;
return listItemText;
}
public List<MobilePhone> Allphones {
get {
phonesForSale = new List<MobilePhone>();
int count = Count;
Index = 0;
while (Index < count) {
phoneID = Convert.ToInt32(dbConnection.DataTable.Rows[Index]["PhoneId"]);
operatingSystem = Convert.ToString(dbConnection.DataTable.Rows[Index]["OperatingSystem"]);
make = Convert.ToString(dbConnection.DataTable.Rows[Index]["Make"]);
model = Convert.ToString(dbConnection.DataTable.Rows[Index]["Model"]);
string conditionString = Convert.ToString(dbConnection.DataTable.Rows[Index]["Condition"]);
originalPrice = Convert.ToInt32(dbConnection.DataTable.Rows[Index]["OriginalPrice"]);
datePurchase = Convert.ToDateTime(dbConnection.DataTable.Rows[Index]["DatePurchased"]);
description = Convert.ToString(dbConnection.DataTable.Rows[Index]["Description"]);
// Set Condition
if (conditionString == "Poor") {
condition = MobilePhone.Condition.Poor;
} else if (conditionString == "Fair") {
condition = MobilePhone.Condition.Fair;
} else if (conditionString == "Good") {
condition = MobilePhone.Condition.Good;
} else if (conditionString == "Mint") {
condition = MobilePhone.Condition.Mint;
}
//check Operating System
if (operatingSystem == "IOS") {
phone = new ApplePhone(make, model, originalPrice, datePurchase, condition, description);
//ApproxValue = ApplePhone.CalculateApproximateValue();
} else if (operatingSystem == "Android") {
phone = new AndroidPhone(make, model, originalPrice, datePurchase, condition, description);
//ApproxValue = AndroidPhone.CalculateApproximateValue();
}
Index++;
phonesForSale.Add(phone);
}
return phonesForSale;
}
}
And the form code is:
public partial class FormMain : Form {
public FormMain() {
InitializeComponent();
Shop shop = new Shop("");
}
private void FormMain_Load(object sender, EventArgs e) {
DisplayItems("");
}
protected int DisplayItems(string operatingSystem) {
Shop MyShop = new Shop("");
Int32 RecordCount;
Int32 Index = 0;
Int32 PID;
if (operatingSystem != "") {
MyShop.FilterByOperatingSystem(operatingSystem);
} else {
MyShop.SelectAll();
}
RecordCount = MyShop.Count;
ArrayList MyPhones = new ArrayList();
while (Index < RecordCount) {
// I Suspect this line is the problem but don't know how to fix it
PID = MyShop.Allphones[Index].PhoneID
string listItemText = MyShop.DescribeCurrentPhone(PID);
//add the new item to the list
MyPhones.Add(listItemText);
//increment the index
Index++;
}
listBox1.DataSource = MyPhones;
return RecordCount;
}
I am not used to connecting to databases, so any advice will be of help!
An example of an alternative to the DB connection you have made is below
List<MyPhone> myIPhoneList = new List<Myphone>();
List<MyPhone> myAndroidList = new List<Myphone>();
SqlConnection myDBConnection = new SqlConnection("MyConnectionString"); //DB Connection
SqlCommand dbCommand = new SqlCommand("SelectAllPhones"); //Stored Procedure
SqlDataReader recordReader = dbCommand.ExecuteReader(); //Execute
//Read records return in to phone objects
while (recordReader.Read()) {
var phoneField1 = recordReader["PhoneField1FromDatabase"];
var phoneField2 = recordReader["PhoneField2FromDatabase"];
//etc...
var myPhone = new MyPhone();
myPhone.Name = phoneField1;
//etc...
if (myPhone.OS == "iPhone")
myIPhoneList.Add(myPhone);
if (myPhone.OS = "Android")
myAndroidList.Add(myPhone);
}
Just a twist to Wheels answer really,
I'd personally put a filter on the stored-proc.
SqlCommand dbCommand = new SqlCommand("SelectAllPhones"); //Stored Procedure
becomes something like:
using (SqlConnection conn = new SqlConnection())
{
using (SqlCommand cmd = new SqlCommand("SelectAllPhones", conn))
{
cmd.Parameters.Add(new SqlParameter() { ParameterName = "#OS", SqlDbType = SqlDbType.VarChar, Direction = ParameterDirection.Input, Value = phoneOS });
cmd.CommandType = CommandType.StoredProcedure;
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
// load your data...
}
}
}
Only because there is very little point dragging both sets of phone data (android/iphone) for each class. You may as well only pull back the data you require.
Of course the Stored-Proc will need an update to cater for the parameter.
something like:
AND PhoneOS = #OS
needs appending to your SQL condition.
clsDataConnection dbConnection; is unknown to me - is this a third party library or a class you've wrote and not included?
public Int32 Count
{
get
{
//return the count of records
return dbConnection.Count;
}
}
dbConnection.Count seems very non-standard. Doesn't read as if you're trying to get the number of rows, more the number of connections - which is invalid here.
dbConnection.DataTables[0].Rows.Count; would be a better way of determining the rows using your existing code, as currently it reads as if your counting the number of database connections which isn't what your after - and would be redundant if using either mine or Wheels as you wont need to know beforehand how many rows your about to process.

IsPostBack Issue

I am trying to do a 3 tier volunteers sign up for packaging session system. First, on the page load, I get the details of certain packaging session:
if (!IsPostBack)
{
string packingID = Request.QueryString["id"];
packingIndv = packing.getPacking(packingID);
if (packingIndv == null)
{
lbl_msg.Text = "Error in getting packing session details!";
}
else
{
lbl_ID.Text = packingIndv.packingID;
lbl_date.Text = packingIndv.date.ToString("dd/M/yyyy", CultureInfo.InvariantCulture); ;
lbl_location.Text = packingIndv.location;
lbl_volunteerAvailable.Text = packingIndv.volunteerAvailable.ToString();
lbl_status.Text = packingIndv.status;
}
}
After that, volunteers can click on the join button, and the program will execute:
In presentation layer after join button is on click:
string userLogged = Session["userLogged"].ToString();
UserBLL user = new UserBLL();
string userID = user.getUserIDByName(userLogged);
PackingBLL packing = new PackingBLL();
string msg = "";
msg = packing.joinPacking(userID, lbl_ID.Text);
lbl_msg.Text = msg;
In business logic layer:
public string joinPacking(string userID, string packingID)
{
string returnMessage = "";
if(returnMessage.Length == 0)
{
Packing packing = new Packing(userID, packingID);
Boolean success = packing.checkJoinedSession();
if (success)
{
returnMessage += "Same volunteer cannot join same packing session for more than once! <br/>";
}
else
{
int nofRows = 0;
nofRows = packing.joinPacking();
if (nofRows > 0)
{
returnMessage = "Request to volunteer for packing session saved successfully.";
int successUpdate = packing.updateRemaining();
if (successUpdate > 0)
{
getPacking(packingID);
}
}
else
{
returnMessage = "Error! Please try again.";
}
}
}
return returnMessage;
}
In data access layer:
public int updateRemaining()
{
int result = 0;
using (var connection = new SqlConnection(FFTHDb.connectionString)) // get your connection string from the other class here
{
SqlCommand command = new SqlCommand("UPDATE PackingSession SET volunteerAvailable = volunteerAvailable + 1 WHERE packingID = '" + packingID + "'", connection);
connection.Open();
result = command.ExecuteNonQuery();
connection.Close();
}
return result;
}
For every join from each volunteer, the volunteer available will be increased by one. What I am trying to do is from the page load, I display the details of packaging session. Then when volunteer joins it, the volunteerAvailable will straight away increased by one. All my database works perfectly, it just wont increase the volunteer available automatically after each successful update sql statement, as in I have to refresh the browser in order to see the changes.

Reading users from Access into a list returns only one user

I'm working on a WPF App in C# with VS 2010 SP1.
I've looked at quite a few examples on here and elsewhere around the web, and my code seems correct, but when I attempt to read rows from an Access DB into a class then into an ObservableCollection (I've also tried just a List), only one ends up in the collection. I then attempt to display a list of usernames in a ListBox, and of course only the one user in the collection appears.
I've been stuck on this for a while now. Any help would be greatly appreciated. I'm hoping it's something very trivial that I'm just overlooking.
User Class:
public class User
{
public User() { }
public int UserID { get; set; }
public string UserName { get; set; }
public string UserTitle { get; set; }
public string UserArea { get; set; }
}
Code:
// Setting up DB stuff.
string s_ConnString = "Provider=Microsoft.ACE.OLEDB.12.0;Data " +
"Source=|DataDirectory|\\CloseoutApp.accdb";
OleDbConnection AccessConn = new OleDbConnection(s_ConnString);
string s_Query = "SELECT UserID, UserName, UserTitle, UserArea FROM Users " +
"ORDER BY UserID;";
OleDbCommand AccessCmd = new OleDbCommand(s_Query, AccessConn);
OleDbDataReader rdr;
AccessConn.Open();
rdr = AccessCmd.ExecuteReader();
// Collection of Users.
ObservableCollection<User> userList = new ObservableCollection<User>();
try
{
// Read each user from DB into a User instance, then add that instance to the userList.
while(rdr.Read())
{
User newUser = new User();
newUser.UserID = rdr.GetInt32(0);
newUser.UserName = rdr.GetString(1);
newUser.UserTitle = rdr.GetString(2);
newUser.UserArea = rdr.GetString(3);
userList.Add(newUser);
}
}
catch(Exception e)
{
//Update Statusbar
}
// Close the DB connection.
rdr.Close();
AccessConn.Close();
// Add users to the ListBox.
foreach(User u in userList)
{
lb_Users.Items.Add(u.UserName);
}
I had something similar happen to me when I was handling my database connection in a similar way.
Give the below code a try:
// Setting up DB stuff.
string s_ConnString = "Provider=Microsoft.ACE.OLEDB.12.0;Data " +
"Source=|DataDirectory|\\CloseoutApp.accdb";
string s_Query = "SELECT UserID, UserName, UserTitle, UserArea FROM Users " +
"ORDER BY UserID;";
ObservableCollection<User> userList = new ObservableCollection<User>();
using (OleDbConnection AccessConn = new OleDbConnection(s_ConnString))
{
using (OleDbCommand AccessCmd = AccessConn.CreateCommand())
{
AccessCmd.CommandText = s_Query;
try
{
AccessConn.Open();
OleDbDataReader rdr = AccessCmd.ExecuteReader();
while (rdr.Read())
{
User newUser = new User();
newUser.UserID = rdr.GetInt32(0);
newUser.UserName = rdr.GetValue(1).ToString();
newUser.UserTitle = rdr.GetValue(2).ToString();
newUser.UserArea = rdr.GetValue(3).ToString();
userList.Add(newUser);
}
rdr.Close();
}
catch(Exception ex)
{
//do something with ex
}
}
}
// Add users to the ListBox.
foreach (User u in userList)
{
lb_Users.Items.Add(u.UserName);
}

Categories

Resources