'SqlServerService' does not implement interface member (C#) - c#

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.

Related

Connection to sql database from visual studio

I'm trying to connect to a database, I also have a bool function to check if the connection worked. I searched all over the internet but can't really find how to do it properly.
public class DBConnection : DBLabsDLL.DBConnectionBase
{
///*
// * The constructor
// */
public DBConnection()
{
string connectionString = null;
SqlConnection connection;
connectionString = "Data Source=SQL Server;Initial Catalog=www3.idt.mdh.se;User ID=ezi15001;Password=********";
connection = new SqlConnection(connectionString);
}
public override bool login(string username, string password)
{
try
{
using (var connection = new SqlConnection(connectionString)
{
connection.Open();
return true;
}
catch (SqlException)
{
return false;
}
}

Pass parameters to factory pattern Architecture in C#

I want to implement factory pattern Architecture. I have created Interface with parameterized function.
1) Step 1 :
public interface IDatabase
{
bool Create(string userId,string password,string host,string dbName);
bool Delete(string userId, string password, string host, string dbName);
}
Step 2:
This interface is Implemented in below class:-
public class IntialDBSetup : IDatabase
{
public bool Create(string userId, string password, string host, string dbName)
{
SqlConnection con = new SqlConnection("Data Source=" + host + ";uid=" + userId + ";pwd=" + password + "");
try
{
string strCreatecmd = "create database " + dbName + "";
SqlCommand cmd = new SqlCommand(strCreatecmd, con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
var file = new System.IO.FileInfo(System.Web.HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["ScriptLocation"]));
string strscript = file.OpenText().ReadToEnd();
string strupdatescript = strscript.Replace("[OWpress]", dbName);
var server = new Microsoft.SqlServer.Management.Smo.Server(new Microsoft.SqlServer.Management.Common.ServerConnection(con));
server.ConnectionContext.ExecuteNonQuery(strupdatescript);
con.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
public bool Delete(string userId, string password, string host, string dbName)
{
throw new NotImplementedException();
}
}
Step 3:
created factory class
public class DBFactory
{
public static IDatabase DbSetup(string DbType, string userId, string password, string host, string dbName)
{
try
{
if (DbType == DBTypeEnum.IntialDB.ToString())
{
return new IntialDBSetup();
}
}
catch (Exception ex)
{
throw new ArgumentException("DB Type Does not exist in our Record");
}
return null;
}
}
Here I want to pass some parameter to my class, Hgow can I get this?
Add a constructor to your class.
If DBFactory and IntialDBSetup are in the same assembly then that constructor can be marked internal (preventing code outside the assembly creating instances directly).
If the factory method was a static member of IntialDBSetup then the constructor can be private preventing direct creation even in the same assembly.

WCF TransactionScope doesnt RollBack

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.

Passing values from SQL to WCF

Am using CLR Trigger to pass the values to WCF,everything works fine but when try to pass the constant value its not pass thru WCF even its not throwing any exception.
CLR Trigger
public partial class Triggers
{
public static EndpointAddress endpoint = new EndpointAddress(new Uri("http://localhost:8000/services/myservice"));
public static WSHttpBinding httpBinding = new WSHttpBinding();
public static ServiceClient.ServiceReference1.ServiceContractClient myclient = new ServiceClient.ServiceReference1.ServiceContractClient(httpBinding, endpoint);
public delegate void MyDelagate(String crudType);
[SqlProcedure()]
[Microsoft.SqlServer.Server.SqlTrigger(Name = "WCFTrigger",
Target = "tbCR", Event = "FOR UPDATE, INSERT")]
public static void Trigger1()
{
SqlCommand cmd;
SqlTriggerContext myContext = SqlContext.TriggerContext;
SqlPipe pipe = SqlContext.Pipe;
SqlDataReader reader;
if(myContext.TriggerAction== TriggerAction.Insert)
{
using (SqlConnection conn = new SqlConnection(#"context connection=true"))
{
conn.Open();
cmd = new SqlCommand(#"SELECT * FROM tbCR", conn);
reader = cmd.ExecuteReader();
reader.Read();
//get the insert value's here
string Name;
Name = reader[1].ToString();
reader.Dispose();
myclient.InsertOccured(Name);
}
}
}
}
}
Interface
namespace SampleService
{
[ServiceContract]
interface IServiceContract
{
[OperationContract]
void UpdateOccured();
[OperationContract]
void InsertOccured(String Name);
}
}
Contract
namespace SampleService
{
class MyService : IServiceContract
{
public void InsertOccured(string Name)
{
Console.WriteLine("Insert Occured",Name);
}
}
}
every time i insert record ,WCF shows "Insert Occured" only but i was expecting "Insert Occured, Test".
Can you please guide me what i suppose to do to get the constant value from SLQ Tirgger.
In your service operation implementation is looks like you need to add the string parameter to your Console.WriteLine() string template. In other words:
Console.WriteLine("Insert Occured, {0}",Name);
You can find more about Console.WriteLine and composite formatting here:
http://msdn.microsoft.com/en-us/library/828t9b9h.aspx

Data Layer Abstract Factory

I'm new on developing an Abstract Factory pattern, and would like to create an abstract factory in the data layer that will help me link this layer to any other databases for example sql and oracle. Can you help me on developing this task please. Note that the connection string of the database will be found in this layer not in the presentation..
Thanks
EDITED
public abstract class Database
{
public string connectionString;
#region Abstract Functions
public abstract IDbConnection CreateConnection();
public abstract IDbCommand CreateCommand();
public abstract IDbConnection CreateOpenConnection();
public abstract IDbCommand CreateCommand(string commandText, IDbConnection connection);
public abstract IDbCommand CreateStoredProcCommand(string procName, IDbConnection connection);
public abstract IDataParameter CreateParameter(string parameterName, object parameterValue);
#endregion
}
public class SQLDatabase : Database
{
public override IDbConnection CreateConnection()
{
return new SqlConnection(connectionString);
}
public override IDbCommand CreateCommand()
{
return new SqlCommand();
}
public override IDbConnection CreateOpenConnection()
{
SqlConnection connection = (SqlConnection)CreateConnection();
connection.Open();
return connection;
}
public override IDbCommand CreateCommand(string commandText, IDbConnection connection)
{
SqlCommand command = (SqlCommand)CreateCommand();
command.CommandText = commandText;
command.Connection = (SqlConnection)connection;
command.CommandType = CommandType.Text;
return command;
}
public override IDbCommand CreateStoredProcCommand(string procName, IDbConnection connection)
{
SqlCommand command = (SqlCommand)CreateCommand();
command.CommandText = procName;
command.Connection = (SqlConnection)connection;
command.CommandType = CommandType.StoredProcedure;
return command;
}
public override IDataParameter CreateParameter(string parameterName, object parameterValue)
{
return new SqlParameter(parameterName, parameterValue);
}
}
Those are the two classes I created..
The functionality already exists.
Add a connection string to app/webb.config:
<connectionStrings>
<add name="TheDatabase" providerName="System.Data.OleDb" connectionString="Provider=OraOLEDB.Oracle.1;Persist Security Info=False;User Id=xxx;Password=yyy;Data Source=zzzz;Extended Properties="/>
</connectionStrings>
Build the connection using a factory:
var connectionString = ConfigurationManager.ConnectionStrings["TheDatabase"];
var providerName = connectionString.ProviderName;
var factory = DbProviderFactories.GetFactory(providerName);
Get a connection:
var connection = factory.CreateConnection();
Get a command:
var command == connection.CreateCommand();
The only thing you need to do is to switch driver in the app/web.config. No other changes are required.
Update
public class Database
{
public static IDbConnection CreateOpenConnection()
{
var connectionString = ConfigurationManager.ConnectionStrings["TheDatabase"];
var providerName = connectionString.ProviderName;
var factory = DbProviderFactories.GetFactory(providerName);
var connection = factory.CreateConnection();
connection.Open();
return connection;
}
}
class FlowerManager : DataWorker
{
public static void GetFlowers()
{
using (IDbConnection connection = Database.CreateOpenConnection())
{
using (IDbCommand command = connection.CreateCommand("SELECT * FROM FLOWERS", connection))
{
using (IDataReader reader = command.ExecuteReader())
{
// ...
}
}
}
}
}
Much of the required functionality can be obtained from
System.Data.Common.DbProviderFactories
where you can get items of System.Data.Common.DbProviderFactory which are implemented by most dotnet-databaseproviders.
Update:
havig your own factory is fine. if you are lookig for examples of working database-factories see the sourcecode of
queryexpress a working database-querying gui,
queryexplus a spinof of queryexpress
mygeneration a codegenerator which connects to many different databases
NHibernate with a sophisticated driver modell for many databases
I would not have "createcommand" or "createconnection" methods.
A much better approach to take is to let each of the access methods (like "GetAccounts") handle their own connection / command instantiation.
Connection and Command objects implement IDisposable. As such it is better to have using statements in which those are created and disposed of as necessary. Teh way you have it now could lead to massive memory issues.
Further the CreateParameter method appears to not provide any real benefit over just calling "new SqlParameter" in the code that needs to create those parameters.
I would do the following:
public interface IDbAccess {
String ConnectionString;
Collection<Account> GetAccountsById(Int32 id);
Boolean StoreAccount(Account acct);
}
public class SqlDatabase : IDbAccess {
public String ConnectionString {get; set;}
public SqlDatabase(String connection) {
ConnectionString = connection;
}
public Collection<Account> GetAccountsById(Int32 id) {
using (SqlConnection connect = new SqlConnection(ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(connect)) {
/// etc.
}
}
}
}
This way your datalayer is specific to the functionality you are providing. There are already great wrappers for db access like Enterprise Library. The approach you are taking adds nothing and introduces errors.
Further this approach means you can implement non-database providers like XML, web services, etc with zero code changes.
Hi People i know this is old post, but i would like share something with you.
The Enterprise Library and OleDb has some problem, when you want to insert image bigger than 32k it will throw Exception, so de solve this i have done:
Create a project Which you can call CustomProvider
Create a Classe Which you will call Database
public abstract class Database
{
public string ConnectionString { get; set; } // Preciso uma variavel para guardar o ConnectionString
public IDbConnection Connection { get; set; }
//public abstract string ProviderName { get; } // Preciso uma variavel para guardar o ConnectionString
//public abstract IDbConnection CreateConnection(string ConnectionString);
public abstract IDbConnection CreateConnection(); // Preciso um Metodo Abstract para CreateConnection Para Tratar da Connection
public abstract IDbCommand CreateCommand();
}
}
Create Seccond Class OracleDatabase.cs
Create Third class SQLDatabase.cs
public class OracleDatabase : Database
{
public override IDbConnection CreateConnection()
{
return new OracleConnection(ConnectionString);
}
public override IDbCommand CreateCommand()
{
return new OracleCommand();
}
public override IDbConnection CreateOpenConnection()
{
OracleConnection connection = (OracleConnection)CreateConnection();
connection.Open();
return connection;
}
public override IDbCommand CreateCommand(string commandText, IDbConnection connection)
{
OracleCommand command = (OracleCommand)CreateCommand();
command.CommandText = commandText;
command.Connection = (OracleConnection)connection;
command.CommandType = CommandType.Text;
return command;
}
}
public class SQLDatabase : Database
{
public override IDbConnection CreateConnection()
{
return new SqlConnection(ConnectionString);
}
public override IDbCommand CreateCommand()
{
return new SqlCommand();
}
public override IDbConnection CreateOpenConnection()
{
SqlConnection connection = (SqlConnection)CreateConnection();
connection.Open();
return connection;
}
public override IDbCommand CreateCommand(string commandText, IDbConnection connection)
{
SqlCommand command = (SqlCommand)CreateCommand();
command.CommandText = commandText;
command.Connection = (SqlConnection)connection;
command.CommandType = CommandType.Text;
return command;
}
public override IDbCommand CreateStoredProcCommand(string procName, IDbConnection connection)
{
SqlCommand command = (SqlCommand)CreateCommand();
command.CommandText = procName;
command.Connection = (SqlConnection)connection;
command.CommandType = CommandType.StoredProcedure;
return command;
}
}
and then on the program
Database db = Factory.CreateDatabase("ConnectionString");
try
{
using (IDbConnection w_connection = db.Connection)
{
w_connection.Open();
IDbTransaction transation = w_connection.BeginTransaction();
IDbCommand dbcomand = db.CreateStoredProcCommand("INSERTTEST");
db.AddInParameter(dbcomand, "#ATTCH", DbType.Binary, bytes);
db.ExecuteNonQuery(dbcomand, transation);
transation.Commit();
}
}
catch (Exception)
{
}
}
You must Override all defined method in the Master Class
Create a Factory.cs
public static Database CreateDatabase(string ConnectionString)
{
//var Conn = ConfigurationManager.ConnectionStrings[ConnectionString].ToString();
if (string.IsNullOrEmpty(ConnectionString))
throw new Exception("Connectionstring Not Found" + ConnectionString);
Database db = null;
if (ConfigurationManager.ConnectionStrings[ConnectionString].ProviderName.Contains("Oracle"))
{
db = new OracleDatabase();
db.ConnectionString = GetConnectionString(ConnectionString);
db.Connection = db.CreateConnection();
}
else
{
db = new SQLDatabase();
db.ConnectionString = GetConnectionString(ConnectionString);
db.Connection = db.CreateConnection();
}
return db;
}

Categories

Resources