Populating Interface - c#

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();

Related

Getting Errors when trying to create Generic Binding methods

I have the following interface and class
public interface IOwner
{
int Owner_pkid { get; set; }
string Name { get; set; }
}
public class Owner : IOwner
{
public Owner()
{
}
public int Owner_pkid { get; set; }
public string Name { get; set; }
}
I then have the following Data Access Methods in a separate class
public List<IOwner> GetAllOwners()
{
var sql = "SELECT owner_pkid, name from dbo.Owners ";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.CommandType = CommandType.Text;
List<IOwner> owners = new List<IOwner>();
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
BindResultSet<IOwner>(reader, owners);
return owners;
}
}
private void BindResultSet<T>(SqlDataReader reader, List<T> items) where T : new()
{
int counter = 0;
if (!reader.IsClosed)
{
while (reader.Read())
{
T record = GetNextDataObject<T>(items, counter);
counter++;
BindRecord<T>(reader, record);
}
}
}
private T GetNextDataObject<T>(List<T> items, int pointer) where T : new()
{
if (pointer < items.Count)
{
return items[pointer];
}
else
{
items.Add(new T());
return items[items.Count - 1];
}
}
private void BindRecord<IOwner>(SqlDataReader reader, IOwner owner)
{
owner.Name = (string)reader["name"];
owner.Owner_pkid = (int)reader["owner_pkid"];
}
I am getting 2 separate errors with this code:
In the GetAllOwners method I am getting an error with the call to BindResultSet which says
IOwner must be a non-abstract type with a parameterless constructor in order to be used here
I have a parameterless constrctor on the implementing class - don't think i can add one to the interface
In the final BindRecord method I am getting an error whereby the two property names are not recognized. This is possibly as a result of the first issue
The problem is that you cannot do new on an interface. So "new T" where T is IOwner will not work.
There are a number of different ways to fix this. The cleanest approach would be to add a factory interface whose only purpose is to create IOwner objects, say IOwnerFactory. Instantiate the factory at the top level and pass it down to the methods that need to create objects.
So instead of item.Add(new T()) use item.Add(ownerFactory.Create())

Repository pattern in C# without Entity Framework

I have a new project that requires me to connect to Oracle 9i. I want to use the repository pattern (which I am new at) to organise my code. I will use some stored procedures for some queries.
I want to write my code in such a way that there should be no duplication and also following the best practices.
Please check my code below and let me know if I am doing it right. I have a feeling that I am not.
I tried to read other posts on the same topic but no luck.
public interface IDeliveryRepository : IDisposable
{
IEnumerable<Delivery> GetDeliveries();
Task GetDelivery(int id);
void Insert(Delivery delivery);
void Delete(Delivery delivery);
void Update(Delivery delivery);
}
Repository:
public class DeliveryRepository: IDeliveryRepository
{
public Delivery GetDelivery(int id)
{
Delivery delivery = null;
var sql = "SELECT d.id , o.owner_id, o.name FROM delivery d JOIN owner o on o.id = d.owner_id where id = :t";
using (var con = new OracleConnection(AppConfig.CALL_CENTER_CONNECTION_STRING))
{
con.Open();
using (var cmd = new OracleCommand(sql, con))
{
cmd.BindByName = true;
cmd.Parameters.Add("t", id);
using (var oraReader = cmd.ExecuteReader())
{
while (oraReader.Read())
{
delivery = new Delivery
{
Id = oraReader.GetString(oraReader.GetOrdinal("id")),
Owner = new Owner
{
Id = oraReader.GetString(oraReader.GetOrdinal("owner_id")),
Name = oraReader.GetString(oraReader.GetOrdinal("name"))
}
};
}
}
}
}
return delivery;
}
.
.
.
.
.
You don't need to make your repository IDisposable, and to use Task you should implement your entire class with the Async programming model. I have updated your code below which should get you close to a compiling baseline that you can then extend.
// Removed the IDisposable interface
public interface IDeliveryRepository
{
IEnumerable<Delivery> GetDeliveries();
// Changed the below from a Task to a Delivery as the return type. To use Task,
// your entire implementation should be asynchronous.
Delivery GetDelivery(int id);
void Insert(Delivery delivery);
void Delete(Delivery delivery);
void Update(Delivery delivery);
}
public class DeliveryRepository: IDeliveryRepository
{
public Delivery GetDelivery(int id)
{
Delivery delivery = null;
var sql = "SELECT d.id , o.owner_id, o.name FROM delivery d JOIN owner o on o.id = d.owner_id where id = :t";
using (var con = new OracleConnection(AppConfig.CALL_CENTER_CONNECTION_STRING))
{
con.Open();
using (var cmd = new OracleCommand(sql, con))
{
cmd.BindByName = true;
cmd.Parameters.Add("t", id);
using (var oraReader = cmd.ExecuteReader())
{
while (oraReader.Read())
{
delivery = new Delivery
{
Id = oraReader.GetString(oraReader.GetOrdinal("id")),
Owner = new Owner
{
Id = oraReader.GetString(oraReader.GetOrdinal("owner_id")),
Name = oraReader.GetString(oraReader.GetOrdinal("name"))
}
};
}
}
}
}
return delivery;
}
public void Insert(Delivery delivery)
{
/// Add your code here
throw new NotImplementedException();
}
public void Delete(Delivery delivery);
{
/// Add your code here
throw new NotImplementedException();
}
public void Update(Delivery delivery);
{
/// Add your code here
throw new NotImplementedException();
}
public IEnumerable<Delivery> GetDeliveries();
{
/// Add your code here
throw new NotImplementedException();
}
}

WCFData.Service1 Does not implement interface member

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.

C#: How to Wrap my Unit of Work code in my repository classes

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.

Override a method (return type DBDataReader) and return a different type(SQLDBDataReader)

I am currently implementing a small software that could read data from different DataBases. The followin is the code:
interface Fetch
{
Dictionary<string, DbDataReader> GetData();
}
abstract class Conn : Fetch
{
abstract public void Connect();
abstract public Dictionary<string, SqlDataReader> GetData();
}
class SqlConn : Conn
{
public override void Connect()
{
_connection = new SqlConnection(_connectionString);
try
{
_connection.Open();
}
catch (SqlException dbe)
{
throw dbe;
}
}
public override Dictionary<string, SqlDataReader> GetData()
{
using (_connection)
{
Dictionary<string, SqlDataReader> dataDictionary = new Dictionary<string, SqlDataReader>();
_xmlDoc.Load("Queries.xml");
XPathNavigator navigator = _xmlDoc.CreateNavigator();
XPathNodeIterator iterator = navigator.Select("//query");
while (iterator.MoveNext())
{
_command = new SqlCommand(iterator.Current.ToString());
_command.Connection = _connection;
_command.CommandText = iterator.Current.ToString();
SqlDataReader reader = _command.ExecuteReader() as SqlDataReader;
dataDictionary.Add(iterator.Current.GetAttribute("name", ""), reader);
}
return dataDictionary;
}
}
}
class OraConn : Conn
{
public override void Connect()
{
_connection = new OracleConnection(_connectionString);
}
public override Dictionary<string, OracleDataReader> GetData()
{
using (_connection)
{
Dictionary<string, OracleDataReader> dataDictionary = new Dictionary<string, OracleDataReader>();
_xmlDoc.Load("Queries.xml");
XPathNavigator navigator = _xmlDoc.CreateNavigator();
XPathNodeIterator iterator = navigator.Select("//query");
while (iterator.MoveNext())
{
_command = new OracleCommand(iterator.Current.ToString());
_command.Connection = _connection;
_command.CommandText = iterator.Current.ToString();
OracleDataReader reader = _command.ExecuteReader() as OracleDataReader;
dataDictionary.Add(iterator.Current.GetAttribute("name", ""), reader);
}
return dataDictionary;
}
}
}
But My problem is the return type, SQLDataReader and OraDataReader in the derived class.
This causes a compiler error that states
‘Error 2 'DashBoard.Connection.OraConn.GetData()': return type must be 'System.Collections.Generic.Dictionary' to match overridden member 'DashBoard.Connection.Conn.GetData()
’.
How can I solve this problem? Or is there other ways to implement this funtion?
Thank you!
The method signature has to stay the same, but as long as your sub-classes inherit from DbDataReader you can return other DbDataReader types such as SqlDataReader and it will compile.
for example:
abstract class DbDataReader
{
// ...
}
class SqlDataReader : DbDataReader
{
}
// ...
class SqlConn : Conn
{
public override Dictionary<string, DbDataReader> GetData()
{
return new Dictionary<string, DbDataReader>
{
{ "Key", new SqlDataReader() }
}
}
}
You can try this way:
public interface IValue<T> { T GetValue(); }
public class SomeClass : IValue<DbDataReader>, IValue<SqlDataReader>
{
DbDataReader IValue<DbDataReader>.GetValue() { return objDbDataReader; }
SqlDataReader IValue<SqlDataReader>.GetValue() { return objSqlDataReader; }
}

Categories

Resources