I am creating a system with C# and Windows Forms, and when I tried to implement an interface to generate the base model with the methods for any database that I implement in the system I get an error when trying to pass parameters to the child class of the interface.
I have the following interface:
It is responsible for generating the contract with all the classes that will inherit it.
public interface iDatabase
{
void createConnection();
void CreateUser();
}
and the class DbService:
which is responsible for containing the contract's fixation and allow me not to generate dependency on the project's dependencies, this way I can change the database at any time, I just need to send a new database class as parameter for it to work...
public class DbService
{
private iDatabase _database;
public DbService(iDatabase databaseService)
{
this._database = databaseService;
}
public void connect()
{
this._database.createConnection();
}
public void insertUser()
{
this._database.CreateUser();
}
}
and the dependency's class of SQL Server: this class is responsible for implementing SQL Server specific rules.
namespace TravelCompany.app.repository
{
internal class SqlServerService : iDatabase
{
SqlConnection sqlCon = null;
private string strCon = "Data Source=DESKTOP-UD6EQCL;Initial Catalog=immigration;Integrated Security=True";
private string strSql = string.Empty;
SqlDataAdapter adapt;
SqlCommand command;
public void createConnection()
{
try
{
sqlCon = new SqlConnection(strCon);
sqlCon.Open();
MessageBox.Show("Connection Open !");
}
catch (Exception e)
{
MessageBox.Show("Error to connect Database!", e.Message);
}
}
public void CreateUser()
{
try
{
strSql = "INSERT INTO users (full_name, email, password, cpf, birthday, cep, street, neighborhood, city, uf, complement, passport_number, stack, xp, seniority) VALUES (#full_name, #email, #password, #cpf, #birthday, #cep, #street, #neighborhood, #city, #uf, #complement, #passport_number, #stack, #xp, #seniority)";
command = new SqlCommand(strSql, sqlCon);
command.Parameters.AddWithValue("#full_name", full_name);
command.Parameters.AddWithValue("#email", email);
command.Parameters.AddWithValue("#password", password);
command.Parameters.AddWithValue("#cpf", cpf);
command.Parameters.AddWithValue("#birthday", birthday);
command.Parameters.AddWithValue("#cep", cep);
command.Parameters.AddWithValue("#street", street);
command.Parameters.AddWithValue("#neighborhood", neighborhood);
command.Parameters.AddWithValue("#city", city);
command.Parameters.AddWithValue("#uf", uf);
command.Parameters.AddWithValue("#complement", complement);
command.Parameters.AddWithValue("#passport_number", passport_number);
command.Parameters.AddWithValue("#stack", stack);
command.Parameters.AddWithValue("#xp", xp);
command.Parameters.AddWithValue("#seniority", seniority);
command.ExecuteNonQuery();
MessageBox.Show("User created successfully!");
}
catch (Exception e)
{
MessageBox.Show("Error to create user!", e.Message);
}
throw new NotImplementedException();
}
}
}
and every time that i try to pass values to the public void CreateUser() of public class SqlServerService i receive an error message:
ERROR: 'iDatabase.CreateUser']1 'SqlServerService' does not implement interface member
The method databaseService.connect(); is working!
the problem is with the 'create user' function of SqlServerService...
but the error appears only when I try to pass parameters to the SqlServerService class methods, and I don't know why this happens because I am implementing the interface method with the same name, can someone help?
I would like to solve this error problem and be able to use the create user function of the SqlServerService class with the implementation of the interface
solved the problem, I basically had to pass the same parameters to all the other methods, so the code looks like this:
class SqlServerService
namespace TravelCompany.app.repository
{
internal class SqlServerService : iDatabase
{
SqlConnection sqlCon = null;
private string strCon = "Data Source=DESKTOP-UD6EQCL;Initial Catalog=immigration;Integrated Security=True";
private string strSql = string.Empty;
SqlDataAdapter adapt;
SqlCommand command;
public void createConnection()
{
try
{
sqlCon = new SqlConnection(strCon);
sqlCon.Open();
MessageBox.Show("Connection Open !");
}
catch (Exception e)
{
MessageBox.Show("Error to connect Database!", e.Message);
}
}
public void CreateUser(string userName, string userBirthday, string userCpf, string userCep, string userStreet, string userNeighborhood, string userCity, string userUf, string userComplement, string userEmail, string userPassport, string stack, string xp, string seniority)
{
MessageBox.Show("User created!");
//try
//{
// strSql = "INSERT INTO users (full_name, email, password, cpf, birthday, cep, street, neighborhood, city, uf, complement, passport_number, stack, xp, seniority) VALUES (#full_name, #email, #password, #cpf, #birthday, #cep, #street, #neighborhood, #city, #uf, #complement, #passport_number, #stack, #xp, #seniority)";
// command = new SqlCommand(strSql, sqlCon);
// command.Parameters.AddWithValue("#full_name", userName);
// command.Parameters.AddWithValue("#email", userEmail);
// command.Parameters.AddWithValue("#password", userPassword);
// command.Parameters.AddWithValue("#cpf", userCpf);
// command.Parameters.AddWithValue("#birthday", userBirthday);
// command.Parameters.AddWithValue("#cep", userCep);
// command.Parameters.AddWithValue("#street", userStreet);
// command.Parameters.AddWithValue("#neighborhood", userNeighborhood);
// command.Parameters.AddWithValue("#city", userCity);
// command.Parameters.AddWithValue("#uf", userUf);
// command.Parameters.AddWithValue("#complement", userComplement);
// command.Parameters.AddWithValue("#passport_number", userPassport);
// command.Parameters.AddWithValue("#stack", userStack);
// command.Parameters.AddWithValue("#xp", userXp);
// command.Parameters.AddWithValue("#seniority", userSeniority);
// command.ExecuteNonQuery();
// MessageBox.Show("User created successfully!");
// }
// catch (Exception e)
// {
// MessageBox.Show("Error to create user!", e.Message);
// }
//throw new NotImplementedException();
}
}
}
interface:
public interface iDatabase
{
void createConnection();
void CreateUser(string userName, string userBirthday, string userCpf, string userCep, string userStreet, string userNeighborhood, string userCity, string userUf, string userComplement, string userEmail, string userPassport, string stack, string xp,
string seniority);
}
and the class DbService:
public void insertUser(string userName, string userBirthday, string userCpf, string userCep, string userStreet, string userNeighborhood, string userCity, string userUf, string userComplement, string userEmail, string userPassport, string stack, string xp, string seniority)
{
this._database.CreateUser(userName, userBirthday, userCpf, userCep, userStreet, userNeighborhood, userCity, userUf, userComplement, userEmail, userPassport, stack, xp, seniority);
}
For a reason that i dont know, i have to pass the parameters to all the classes.
How can i sign-out and redirect to the login page from a public static class?
I have tried the following but it does not stop page execution..
public static DatabaseNameEntities CreateEntitiesForSpecificDatabaseName(bool contextOwnsConnection = true)
{
string database_name = "";
try
{
database_name = System.Web.HttpContext.Current.Application["DB_NAME"].ToString();
}
catch (NullReferenceException)
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
//Initialize the SqlConnectionStringBuilder
//Initialize the EntityConnectionStringBuilder
//Create entity connection
EntityConnection connection = new EntityConnection(entityBuilder.ConnectionString);
return new DatabaseNameEntities(connection);
}
I have tried the following but it does not stop page execution..
That's because it's simply not the MVC way. It's also breaks the Single Responsibility Principle, that is, why would a method named CreateEntitiesForSpecificDatabaseName() know anything about MVC or logging out a user. The code you posted generally breaks this principle multiple times (application state, signing out a user).
Additionally, catching an exception you can prevent is also poor practice (or as the Lead Developer for the C# Compiler team called it, Boneheaded Exceptions).
Consider the following code.
public static ControllerBaseExtensions
{
private const string DBNAME = "DB_NAME";
public static bool TryGetDatabaseName(this ControllerBase instance,
out string DbName)
{
DbName = null;
var app = GetApp(instance);
var result = app.Any(k => k == DBNAME);
if (result)
{
DbName = instance.Application[DBNAME] as string;
result = DbName != null;
}
return result;
}
public static void SetDatabaseName(this ControllerBase instance,
string DbName)
{
var app = GetApp(instance);
app[DBNAME] = DbName;
}
private static HttpApplication GetApp(ControllerBase instance)
{
return instance.ControllerContext.HttpContext.Application;
}
}
public ActionResult MyMethod()
{
string DbName;
if (!this.TryGetDatabaseName(out DbName))
{
FormsAuthentication.SignOut();
// http://stackoverflow.com/questions/30509980
RedirectToAction("Login", "Account");
}
CreateEntitiesForSpecificDatabaseName(Dbname);
}
public static DatabaseNameEntities CreateEntitiesForSpecificDatabaseName(
string dbName,
bool contextOwnsConnection = true)
{
//Initialize the SqlConnectionStringBuilder
//Initialize the EntityConnectionStringBuilder
//Create entity connection
EntityConnection connection = new
EntityConnection(entityBuilder.ConnectionString);
return new DatabaseNameEntities(connection);
}
Does simply ie, no try or catch work as expected
public static DatabaseNameEntities CreateEntitiesForSpecificDatabaseName(bool contextOwnsConnection = true)
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
How do i call the Businesslayer that is in the bin folder as a DLL. 'BusinessLogic' is my dll.
namespace BusinessLogic
{
public class BizLogic
{
string DbConnString = DbConnectionStrings.GetDbConnectionString();
public Dataset SignIn(string Username, string Password)
{
string strReturn = string.Empty;
DataSet pds = new DataSet();
try
{
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#UserName", UserName )
,new SqlParameter("#Password", Password )
};
SqlHelper.FillDataset(DbConnString, System.Data.CommandType.StoredProcedure, "RepSignIn", pds, new string[] { "SignIn" }, parameters);
return pds;
}
catch (Exception ex)
{
return null;
}
}
}
}
The below part of the code used to work earlier but i changed the database from SQl 2008 R2 Express to 2008 R2 Web Edition with Windows Authentication, it stopped working. I cannot debug because its a DLL and when i have the Quickwatch on BusinssLogic, i see an error " BusinessLogic 'BusinessLogic' is a 'namespace', which is not valid in the given context
". This is in VS 2008.
DataSet ds = new BusinessLogic.BizLogic().SignIn(string Username, string Password);
Can someone please help me what is that i am missing. The connectionString in Web.config is like this
namespace BusinessLogic
{
public class DbConnectionStrings
{
private const string dbConnectionString = "ConnectionString";
public static string GetDbConnectionString()
{
return GetConnectionStringFromConfigFile(dbConnectionString);
}
private static string GetConnectionStringFromConfigFile(string ConnectionName)
{
string connstring = string.Empty;
try
{
connstring = System.Configuration.ConfigurationSettings.AppSettings[ConnectionName];
}
catch
{
}
return connstring;
}
public DbConnectionStrings()
{
}
}
}
Please let me know if you need to know anything else to guide me!
Thank you very much in advance!
I have used this guid: http://www.c-sharpcorner.com/uploadfile/shivprasadk/wcf-faq-part-5-transactions/
Why doesnt it rollback?? I dont understand!
I have a service and client Application and I dont have a clue what is the problem with this code.
after doing this line perfectly and save it in my DB,
proxy.AddEmployee("Stav", "20");
the next line throw Exception becouse I didnt send a number to the Age parameter, but the Transaction doesnt RollBack the first line so the Information : Stav, 20 still exsist in my DB!
proxy.AddEmployee("Stav123", "Not a Number(-->will do Exception)")
EDIT 1:
I add the AddEmployee implement.
client:
static void Main(string[] args)
{
ServiceReference1.IJob proxy = new ServiceReference1.JobClient();
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
try
{
proxy.AddEmployee("Stav", "20");
proxy.AddEmployee("Stav123", "Not a Number(-->will do Exception) ");//stop the running and show the Exception but keep the stav,20 in DB
ts.Complete();
}
catch
{
ts.Dispose();
}
}
}
service:
[ServiceContract]
public interface IJob
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void AddEmployee(string Name, string Age);
}
public class JobImplement:IJob
{
[OperationBehavior(TransactionScopeRequired = true)]
public void AddEmployee(string Name, string Age)
{
string strConnection = #"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\stavalfi\Desktop\WCF2\ConsoleApplication4\WCF_DB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
SqlConnection objConnection = new SqlConnection(strConnection);
objConnection.Open();
SqlCommand objCommand = new SqlCommand("INSERT INTO Employee (Name,Age) " + "VALUES ('" + Name + "' ,'" + Age + "')", objConnection);
objCommand.ExecuteNonQuery();
objConnection.Close();
}
}
static void Main(string[] args)
{
WSHttpBinding Basic = new WSHttpBinding();
Basic.TransactionFlow = true;
ServiceHost host = new ServiceHost(typeof(JobImplement), new Uri("http://localhost:8080"));
//
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(behavior);
//
host.AddServiceEndpoint(typeof(IJob), new BasicHttpBinding(), "Request123");
host.Open();
//
Console.WriteLine("opened");
Console.ReadLine();
//
host.Close();
}
It looks like you have a possible typo in your code here:
static void Main(string[] args)
{
...
host.AddServiceEndpoint(typeof(IJob), new BasicHttpBinding(), "Request123");
...
}
You are adding an endpoint of type BasicHttpBinding - a binding protocol that does not support transactions.
I am thinking that you actually meant to do this:
static void Main(string[] args)
{
WSHttpBinding Basic = new WSHttpBinding();
Basic.TransactionFlow = true;
...
host.AddServiceEndpoint(typeof(IJob), Basic, "Request123");
...
}
That would give you a WSHttpBinding endpoint - a binding protocol that does support transactions.
You should implement your own rollback function. Here's a basic way to do it. In your Service class interface add the [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] attribute. Then add these codes:
private SqlCommand Command { get; set; }
[OperationContract]
public void BeginTransaction()
{
this.Command = new SqlCommand();
string strConnection = #"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\stavalfi\Desktop\WCF2\ConsoleApplication4\WCF_DB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
SqlConnection objConnection = new SqlConnection(strConnection);
objConnection.Open();
this.Command.Connection = objConnection;
}
[OperationContract]
public void RollBackTransaction()
{
this.Command.Transaction.Rollback();
}
[OperationContract]
public void CommitTransaction()
{
this.Command.Transaction.Commit();
}
[OperationContract]
public void CloseConnection()
{
this.Command.Connection.Close();
this.Command = null;
}
[OperationBehavior(TransactionScopeRequired = true)]
public void AddEmployee(string Name, string Age)
{
this.Command.CommandText = "INSERT INTO Employee (Name,Age) " + "VALUES ('" + Name + "' ,'" + Age + "')";
this.Command.ExecuteNonQuery();
}
Then you can access it in the Client code like this:
try
{
proxy.BeginTransaction();
proxy.AddEmployee("Stav", "20");
proxy.AddEmployee("Stav123", "Not a Number(-->will do Exception)");
proxy.CommitTransaction();
}
catch
{
proxy.RollBackTransaction();
}
finally
{
proxy.CloseConnection();
}
Hope this helps.