I am following a guide on WCF on C# using visual studio 2010. I thought I was doing everything correct, till I built the solution and I am meet with this error. Can someone tell me what to do and how to fix it? Also why its happening? I am fairly new to this, so any help will be greatly appericated.
This is my code. The error appears in the first line, in Service1 : IService1. I do see the note but I tried changing service1 to say "Hello" but no luck.
namespace WCFData
{
// NOTE: You can use the "Rename" command on the "Refactor" menu
// to change the class name "Service1" in both code
// and config file together.
public class Service1 : IService1
{
SqlConnection conn;
SqlCommand comm;
SqlConnectionStringBuilder connStringBuilder;
void ConnectToDB()
{
connStringBuilder = new SqlConnectionStringBuilder();
connStringBuilder.DataSource = "NATHAN-PC\\SQLEXPRESS";
connStringBuilder.InitialCatalog = "WCF";
connStringBuilder.Encrypt = true;
connStringBuilder.TrustServerCertificate = true;
connStringBuilder.ConnectTimeout = 30;
connStringBuilder.MultipleActiveResultSets = true;
connStringBuilder.IntegratedSecurity = true;
conn = new SqlConnection(connStringBuilder.ToString());
conn = conn.CreateCommand();
}
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
public int InsertPerson(Person p)
{
try
{
comm.CommandText = "INSERT INTO Person Values(#Id, #Name, #age)";
comm.Parameters.AddWithValue("Id", p.Id);
comm.Parameters.AddWithValue("Name", p.Name);
comm.Parameters.AddWithValue("Age", p.Age);
comm.CommandType = CommandType.Text;
conn.Open();
return comm.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (conn != null)
{
conn.Close();
}
}
}
}
}
You can right click on the interface IService1 and select "Implement Interface."
This will add the appropriate methods to your class.
Then check if you are misspelling their signatures in your code.
Related
See my repository code
public abstract class AdoRepository<T> where T : class
{
private static SqlConnection _connection;
public AdoRepository(string connectionString)
{
_connection = new SqlConnection(connectionString);
}
public virtual T PopulateRecord(SqlDataReader reader)
{
return null;
}
public virtual void GetDataCount(int count)
{
}
protected IEnumerable<T> GetRecords(SqlCommand command)
{
var list = new List<T>();
command.Connection = _connection;
_connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
while (reader.Read())
{
list.Add(PopulateRecord(reader));
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
GetDataCount(Convert.ToInt32(reader["Count"].ToString()));
}
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
catch(Exception ex)
{
string Msg = ex.Message;
}
finally
{
_connection.Close();
}
return list;
}
protected T GetRecord(SqlCommand command)
{
T record = null;
command.Connection = _connection;
_connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
while (reader.Read())
{
record = PopulateRecord(reader);
break;
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
finally
{
_connection.Close();
}
return record;
}
protected IEnumerable<T> ExecuteStoredProc(SqlCommand command)
{
var list = new List<T>();
command.Connection = _connection;
command.CommandType = CommandType.StoredProcedure;
_connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
while (reader.Read())
{
var record = PopulateRecord(reader);
if (record != null) list.Add(record);
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
finally
{
_connection.Close();
}
return list;
}
}
public class StudentRepository : AdoRepository<Student>
{
public int DataCounter { get; set; }
public StudentRepository(string connectionString)
: base(connectionString)
{
}
public IEnumerable<Student> GetAll()
{
// DBAs across the country are having strokes
// over this next command!
using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents"))
{
return GetRecords(command);
}
}
public Student GetById(string id)
{
// PARAMETERIZED QUERIES!
using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE Id = #id"))
{
command.Parameters.Add(new ObjectParameter("id", id));
return GetRecord(command);
}
}
public IEnumerable<Student> GetStudents(int StartIndex, int EndIndex, string sortCol, string sortOrder)
{
string strSQL = "SELECT * FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
strSQL += " ORDER BY " + sortCol + " " + sortOrder;
strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
var command = new SqlCommand(strSQL);
return GetRecords(command);
}
public override Student PopulateRecord(SqlDataReader reader)
{
return new Student
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateName = reader["StateName"].ToString(),
CityName = reader["CityName"].ToString()
};
}
public override void GetDataCount(int count)
{
DataCounter = count;
}
}
this way unit of work code added
public class UnitOfWorkFactory
{
public static IUnitOfWork Create()
{
var connection = new SqlConnection(ConfigurationManager.ConnectionStrings("MyDb").ConnectionString);
connection.Open();
return new AdoNetUnitOfWork(connection, true);
}
}
public class AdoNetUnitOfWork : IUnitOfWork
{
public AdoNetUnitOfWork(IDbConnection connection, bool ownsConnection)
{
_connection = connection;
_ownsConnection=ownsConnection;
_transaction = connection.BeginTransaction();
}
public IDbCommand CreateCommand()
{
var command = _connection.CreateCommand();
command.Transaction = _transaction;
return command;
}
public void SaveChanges()
{
if (_transaction == null)
throw new InvalidOperationException("Transaction have already been commited. Check your transaction handling.");
_transaction.Commit();
_transaction = null;
}
public void Dispose()
{
if (_transaction != null)
{
_transaction.Rollback();
_transaction = null;
}
if (_connection != null && _ownsConnection)
{
_connection.Close();
_connection = null;
}
}
}
using (var uow = UnitOfWorkFactory.Create())
{
var repos = new UserRepository(uow);
uow.SaveChanges();
}
public class UserRepository
{
private AdoNetUnitOfWork _unitOfWork;
public UserRepository(IUnitOfWork uow)
{
if (uow == null)
throw new ArgumentNullException("uow");
_unitOfWork = uow as AdoNetUnitOfWork;
if (_unitOfWork == null)
throw new NotSupportedException("Ohh my, change that UnitOfWorkFactory, will you?");
}
public User Get(Guid id)
{
using (var cmd = _unitOfWork.CreateCommand())
{
cmd.CommandText = "SELECT * FROM Users WHERE Id = #id");
cmd.AddParameter("id", id);
// uses an extension method which I will demonstrate in a
// blog post in a couple of days
return cmd.FirstOrDefault<User>();
}
}
}
but i want to add unit of work code in my repository class. may be in AdoRepository class or StudentRepository class as a result i do not have to write the below code again and again.
using (var uow = UnitOfWorkFactory.Create())
{
var repos = new UserRepository(uow);
uow.SaveChanges();
}
so when i will be working with any repository like UserRepository then i have to repeat again and again this lines of code UnitOfWorkFactory.Create() which i do not want rather i am looking for a way to embed unit of work code in some where centralize as a result i could reduce the repeated code.
so looking for idea and suggestion. if possible give me modified version of code.
thanks
I will be straightforward about this:
A UoW that contains repositories is an anti pattern at least if DDD is involved. If it isn't, then you're dealing with a very simple app so make you life easier and use a ORM which implements what you want.
As a thumb rule, a repository may contain a UoW as an implementation detail and you should be certain that you really need a repository. A repository inside a UoW is a very specific case which is valid ONLY with CRUD apps and you'll just be reinventing a very small part of an ORM.
Using ado.net directly is wasting time (and money). Either use an ORM or a data mapper aka micro-ORM. With the latter option the UoW is the Db transaction.
You don't gain anything significant using Ado.Net,the performance gain is so small it's not even funny (I know that because I've benchmarked it). The only thing you'll get is longer devel time and human errors.
Actually, if I take a better look at your code, you're basically building a micro ORM, without knowing it. It's still not a repository though, because the abstraction doesn't have business semantics and it's too tightly coupled to an implementation detail.
Can anyone tell me how do I populate my fields in my interface IAccount? I'm having an error in x.Add(new IAccount ...
public class IPersonRepo : IAccount
{
string connectionstring = #"Server=SLI002/SQLEXPRESS;Database=atengturonDB;Trusted_Connection=true;";
public int AccountsID
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public byte[] AccountUserName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public byte[] AccountPassword
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public byte[] AccountSalt
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public void getAccount()
{
SqlConnection conn = new SqlConnection(connectionstring);
using (SqlCommand comm = new SqlCommand())
{
List<IAccount> x = new List<IAccount>();
comm.Connection = conn;
comm.CommandText = "Select AccountsID,AccountsUserName,AccountsPassword,AccountsSalt from Accounts";
comm.CommandType = CommandType.Text;
SqlDataReader reader = null;
conn.Open();
comm.ExecuteNonQuery();
reader = comm.ExecuteReader();
while (reader.Read())
{
x.Add(new IAccount
{
AccountsID = (int)reader["AccountsID"],
AccountUserName = (byte[])reader["AccountsUserName"],
AccountPassword = (byte[])reader["AccountsPassword"],
AccountSalt = (byte[])reader["AccountsSalt"]
});
}
conn.Close();
}
}
}
Please, rename IPersonRepo to PersonRepo, prefix I means interface, but clearly it is class. Second, it doesnt look like repo (=repository) but like Person (but this is debatable... :) )
Third, you are trying to create interface - but you have to instance class which implements that interface:
//x.Add(new IAccount
//x.Add(new IPersonRepo
//x.Add(new PersonRepo
x.Add(new Person
{
AccountsID = (int)reader["AccountsID"],
AccountUserName = (byte[])reader["AccountsUserName"],
AccountPassword = (byte[])reader["AccountsPassword"],
AccountSalt = (byte[])reader["AccountsSalt"]
});
Fourth and last, maybe you should take a look at any ORM, like NHibernate or Entity Framework. Can help you, but its your call :)
First, never use the I prefix when deciding on a class name. It's not a compilation error but it's very confusing since the convention is to use I as a prefix to interface names.
So your class should be called PersonRepo and not IPersonRepo.
(you can, however, name a class that starts with I like (Ice), just don't use I as a prefix)
Second, you can't instantiate an interface. you can use a variable of the interface type but instantiate the actual class: IAccount MyAccount = new PersonRepo();
I am a newbie to 3 tier architecture and below is my DAL code
public static int Insert(string firstname, string lastname, DateTime dob, string gender,string email, string password)
{
// bool flag = false;
SqlParameter pid;
SqlParameter result;
SqlConnection con = Generic.DBConnection.OpenConnection();
try
{
SqlCommand cmd1 = new SqlCommand("Insertreg", con);
cmd1.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.AddWithValue("#FirstName", firstname);
cmd1.Parameters.AddWithValue("#LastName", lastname);
cmd1.Parameters.AddWithValue("#Dob", dob);
cmd1.Parameters.AddWithValue("#Gender", gender);
cmd1.Parameters.AddWithValue("#EmailId", email);
cmd1.Parameters.AddWithValue("#Password", password);
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
pid = cmd1.Parameters.Add("#id", System.Data.SqlDbType.Int);
pid.Direction = System.Data.ParameterDirection.Output;
return cmd1.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
throw ex;
}
}
this in BAL
public int insert(string firstname,string lastname,DateTime dob,string gender,string email,string password)
{
ProfileMasterDAL dal=new ProfileMasterDAL();
try
{
return ProfileMasterDAL.Insert(firstname, lastname, dob, gender,email, password);
}
catch (Exception ex)
{
throw ex;
}
finally
{
dal = null;
}
}
I my UI
ProfileMasterBLL pmBLL = new ProfileMasterBLL();
pmBLL.insert(firstname, lastname, dob, gender, mobile, country, state, email, password);
Is this the correct way to code in 3 tier??I mean how to call methods from DAL to BAL and into UI?If not suggest me some good way.Thanks.
Normally I do the following:
Define a Business Layer (BL, you call it BAL). This contains the definitions of you business entities. It also defines interfaces to retrieve/save/delete data for whatever patterns you use (repository, context, etc).
Define a Data Access Layer (DAL). This contains the actual implementation for the retrieve/save/delete interfaces.
Define a UI layer. This contains UI elements (forms, controls, models, controllers, etc), which can use the BL to load data.
The references are the following:
The BL doesn't know the DAL or the UI.
The DAL knows the BL. The DAL does not know the UI.
THe UI knows the BL. The UI does not know the DAL.
The big question for you probably is, how does the BL retrieve/save/delete data when it doesn't know the DAL, and therefore cannot create an instance of a class in the DAL. Well, this is where a little Dependency Injection comes in handy. All you have to wire up is the injection of the DAL-class to the BL-interface.
Hope this makes sense. I use it as my standard 3-tier implementation, and it works absolutely without problems. Specifically, I use Entity Framework with POCO for entities, and the DI I use is a custom one, but any of the ones out there will do.
UPDATE
The BL does not know the DAL.
The BL defines an interface (lets call it IRepository) which it can use to do what it needs to do.
The DAL defines a class (Repository) which implements the interface IRepository. So the actual implementation of the repository is in the DAL.
Obviously the BL cannot create an instance of the repository directly. This is where dependency injection comes in, this allows the developer to create an instance of a class where it normally cannot be done. A simple crude version of this, is to use reflection.
I hope this makes more sense.
It might help you to see some actual code. I suggest you download NetTiers, run it against your db schema and see the outputted code for the implementation details.
using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.Odbc;
using System.IO;
using System.ComponentModel;
namespace dal
{
/// <summary>
/// Summary description for Data Access Layer
/// </summary>
public class DataAccess
{
public string strConnectionString;
private DbConnection objConnection;
private DbCommand objCommand;
private DbProviderFactory objFactory = null;
private bool boolHandleErrors=false;
private string strLastError;
private bool boolLogError=false;
private string strLogFile;
public DataAccess()
{
//strConnectionString = ;
strConnectionString = objCommon.GetConnectionString;
objFactory = OleDbFactory.Instance;
objConnection = objFactory.CreateConnection();
objCommand = objFactory.CreateCommand();
objConnection.ConnectionString = strConnectionString;
objCommand.Connection = objConnection;
}
public bool HandleErrors
{
get
{
return boolHandleErrors;
}
set
{
boolHandleErrors = value;
}
}
public string LastError
{
get
{
return strLastError;
}
}
public bool LogErrors
{
get
- {
return boolLogError;
}
set
{
boolLogError = value;
}
}
public string LogFile
{
get
{
return strLogFile;
}
set
{
strLogFile = value;
}
}
public int AddParameter(string name, object value)
{
DbParameter p = objFactory.CreateParameter();
p.ParameterName = name;
p.Value = value;
return objCommand.Parameters.Add(p);
}
public int AddParameter(string name, object value, ParameterDirection direction)
{
DbParameter p = objFactory.CreateParameter();
p.ParameterName = name;
p.Value = value;
p.Direction = direction;
return objCommand.Parameters.Add(p);
}
public int AddParameter(string name, object value, DbType type)
{
DbParameter p = objFactory.CreateParameter();
p.ParameterName = name;
p.Value = value;
p.DbType = type;
return objCommand.Parameters.Add(p);
}
public int AddParameter(DbParameter parameter)
{
return objCommand.Parameters.Add(parameter);
}
public DbCommand Command
{
get
{
return objCommand;
}
}
public void BeginTransaction()
{
try
{
if (objConnection.State == System.Data.ConnectionState.Closed)
{
objConnection.Open();
}
objCommand.Transaction = objConnection.BeginTransaction();
}
catch (Exception Ex)
{
HandleExceptions(Ex);
}
}
public void CommitTransaction()
{
objCommand.Transaction.Commit();
objConnection.Close();
}
public void RollbackTransaction()
{
objCommand.Transaction.Rollback();
objConnection.Close();
}
public int ExecuteNonQuery(string query)
{
return ExecuteNonQuery(query, CommandType.Text, ConnectionState.CloseOnExit);
}
public int ExecuteNonQuery(string query, CommandType commandtype)
{
return ExecuteNonQuery(query, commandtype, ConnectionState.CloseOnExit);
}
public int ExecuteNonQuery(string query, ConnectionState connectionstate)
{
return ExecuteNonQuery(query, CommandType.Text, connectionstate);
}
public int ExecuteNonQuery(string query, CommandType commandtype, ConnectionState connectionstate)
{
objCommand.CommandText = query;
objCommand.CommandType = commandtype;
int i = -1;
try
{
if (objConnection.State == System.Data.ConnectionState.Closed)
{
objConnection.Open();
}
i = objCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
HandleExceptions(ex);
}
finally
{
objCommand.Parameters.Clear();
if (connectionstate == ConnectionState.CloseOnExit)
{
objConnection.Close();
}
}
return i;
}
public object ExecuteScalar(string query)
{
return ExecuteScalar(query, CommandType.Text, ConnectionState.CloseOnExit);
}
public object ExecuteScalar(string query, CommandType commandtype)
{
return ExecuteScalar(query, commandtype, ConnectionState.CloseOnExit);
}
public object ExecuteScalar(string query, ConnectionState connectionstate)
{
return ExecuteScalar(query, CommandType.Text, connectionstate);
}
public object ExecuteScalar(string query, CommandType commandtype, ConnectionState connectionstate)
{
objCommand.CommandText = query;
objCommand.CommandType = commandtype;
object o = null;
try
{
if (objConnection.State == System.Data.ConnectionState.Closed)
{
objConnection.Open();
}
o = objCommand.ExecuteScalar();
}
catch (Exception ex)
{
HandleExceptions(ex);
}
finally
{
objCommand.Parameters.Clear();
if (connectionstate == ConnectionState.CloseOnExit)
{
objConnection.Close();
}
}
return o;
}
public DbDataReader ExecuteReader(string query)
{
return ExecuteReader(query, CommandType.Text, ConnectionState.CloseOnExit);
}
public DbDataReader ExecuteReader(string query, CommandType commandtype)
{
return ExecuteReader(query, commandtype, ConnectionState.CloseOnExit);
}
public DbDataReader ExecuteReader(string query, ConnectionState connectionstate)
{
return ExecuteReader(query, CommandType.Text, connectionstate);
}
public DbDataReader ExecuteReader(string query, CommandType commandtype, ConnectionState connectionstate)
{
objCommand.CommandText = query;
objCommand.CommandType = commandtype;
DbDataReader reader = null;
try
{
if (objConnection.State == System.Data.ConnectionState.Closed)
{
objConnection.Open();
}
if (connectionstate == ConnectionState.CloseOnExit)
{
reader = objCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
else
{
reader = objCommand.ExecuteReader();
}
}
catch (Exception ex)
{
HandleExceptions(ex);
}
finally
{
objCommand.Parameters.Clear();
}
return reader;
}
public DataSet ExecuteDataSet(string query)
{
return ExecuteDataSet(query, CommandType.Text, ConnectionState.CloseOnExit);
}
public DataSet ExecuteDataSet(string query, CommandType commandtype)
{
return ExecuteDataSet(query, commandtype, ConnectionState.CloseOnExit);
}
public DataSet ExecuteDataSet(string query, ConnectionState connectionstate)
{
return ExecuteDataSet(query, CommandType.Text, connectionstate);
}
public DataSet ExecuteDataSet(string query, CommandType commandtype, ConnectionState connectionstate)
{
DbDataAdapter adapter = objFactory.CreateDataAdapter();
objCommand.CommandText = query;
objCommand.CommandType = commandtype;
adapter.SelectCommand = objCommand;
DataSet ds = new DataSet();
try
{
adapter.Fill(ds);
}
catch (Exception ex)
{
HandleExceptions(ex);
}
finally
{
objCommand.Parameters.Clear();
if (connectionstate == ConnectionState.CloseOnExit)
{
if (objConnection.State == System.Data.ConnectionState.Open)
{
objConnection.Close();
}
}
}
return ds;
}
private void HandleExceptions(Exception ex)
{
throw ex;
}
private void WriteToLog(string msg)
{
StreamWriter writer = File.AppendText(LogFile);
writer.WriteLine(DateTime.Now.ToString() + " - " + msg);
writer.Close();
}
public void Dispose()
{
objConnection.Close();
objConnection.Dispose();
objCommand.Dispose();
}
public enum Providers
{
SqlServer, OleDb, Oracle, ODBC, ConfigDefined
}
public enum ConnectionState
{
KeepOpen, CloseOnExit
}
public interface ILoadFromDataRow
{
bool LoadFromDataRow(DataRow row);
}
}
}
You can you the following sample code for 3 tier architecture :-
CLASS - BAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
public class BAL
{
DAL objDAL;
public BAL()
{
}
public string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public int insert()
{
objDAL = new DAL();
int val = 0;
try
{
Hashtable objHash = new Hashtable();
objHash.Add("#Name", Convert.ToString(_Name));
val = objDAL.Insert("Your SP Name", objHash);
}
catch (Exception ex)
{
throw ex;
}
finally
{
objDAL = null;
}
return val;
}
}
CLASS - DAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
public class DAL : IDisposable
{
SqlConnection con;
public DAL()
{
con = new SqlConnection("Connection String");
}
public int Insert(string CMD, Hashtable objHash)
{
int val = 0;
try
{
SqlCommand cmd1 = new SqlCommand(CMD, con);
cmd1.CommandType = CommandType.StoredProcedure;
foreach (DictionaryEntry de in objHash)
{
cmd1.Parameters.AddWithValue(Convert.ToString(de.Key), Convert.ToString(de.Value));
}
con.Open();
val = cmd1.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
return val;
}
#region IDisposable Members
public void Dispose()
{
throw new NotImplementedException();
}
#endregion
}
UI:-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
BAL objBAL;
protected void Page_Load(object sender, EventArgs e)
{
Insert();
}
public void Insert()
{
int val = 0;
objBAL = new BAL();
objBAL.Name = "stackoverflow";
try
{
val = objBAL.insert();
}
catch { }
finally
{
objBAL = null;
}
if (val != 0)
{
//Insert sucessful
}
else
{
//Error in Insert.
}
}
}
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.
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