I am trying to implement the Repository Pattern explained by jgauffin at http://ift.tt/1ouayRg and getting crazy!
I have several problems to get it work. I have implemented a small SQL Server table called Employee
:
I created a class for this employee:
Employee
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
IConnectionFactory
public interface IConnectionFactory
{
IDbConnection Create();
}
Is it corect, that there is no correponding implemnetation for the IConnectionFactory interface? I couldnt find it!
AdoNetContext
public class AdoNetContext
{
private readonly IDbConnection _connection;
private readonly IConnectionFactory _connectionFactory;
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
private readonly LinkedList<AdoNetUnitOfWork> _uows = new LinkedList<AdoNetUnitOfWork>();
public AdoNetContext(IConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
_connection = _connectionFactory.Create();
}
public IUnitOfWork CreateUnitOfWork()
{
var transaction = _connection.BeginTransaction();
var uow = new AdoNetUnitOfWork(transaction, RemoveTransaction, RemoveTransaction);
_rwLock.EnterWriteLock();
_uows.AddLast(uow);
_rwLock.ExitWriteLock();
return uow;
}
public IDbCommand CreateCommand()
{
var cmd = _connection.CreateCommand();
_rwLock.EnterReadLock();
if (_uows.Count > 0)
cmd.Transaction = _uows.First.Value.Transaction;
_rwLock.ExitReadLock();
return cmd;
}
private void RemoveTransaction(AdoNetUnitOfWork obj)
{
_rwLock.EnterWriteLock();
_uows.Remove(obj);
_rwLock.ExitWriteLock();
}
public void Dispose()
{
_connection.Dispose();
}
}
AdoNetUnitOfWork
public class AdoNetUnitOfWork : IUnitOfWork
{
private IDbTransaction _transaction;
private readonly Action<AdoNetUnitOfWork> _rolledBack;
private readonly Action<AdoNetUnitOfWork> _committed;
public AdoNetUnitOfWork(IDbTransaction transaction, Action<AdoNetUnitOfWork> rolledBack, Action<AdoNetUnitOfWork> committed)
{
Transaction = transaction;
_transaction = transaction;
_rolledBack = rolledBack;
_committed = committed;
}
public IDbTransaction Transaction { get; private set; }
public void Dispose()
{
if (_transaction == null)
return;
_transaction.Rollback();
_transaction.Dispose();
_rolledBack(this);
_transaction = null;
}
public void SaveChanges()
{
if (_transaction == null)
throw new InvalidOperationException("May not call save changes twice.");
_transaction.Commit();
_committed(this);
_transaction = null;
}
}
AppConfigConnectionFactory
public class AppConfigConnectionFactory
{
private readonly DbProviderFactory _provider;
private readonly string _connectionString;
private readonly string _name;
public AppConfigConnectionFactory(string connectionName)
{
if (connectionName == null) throw new ArgumentNullException("connectionName");
var conStr = ConfigurationManager.ConnectionStrings[connectionName];
if (conStr == null)
throw new ConfigurationErrorsException(string.Format("Failed to find connection string named '{0}' in app/web.config.", connectionName));
_name = conStr.ProviderName;
_provider = DbProviderFactories.GetFactory(conStr.ProviderName);
_connectionString = conStr.ConnectionString;
}
public IDbConnection Create()
{
var connection = _provider.CreateConnection();
if (connection == null)
throw new ConfigurationErrorsException(string.Format("Failed to create a connection using the connection string named '{0}' in app/web.config.", _name));
connection.ConnectionString = _connectionString;
connection.Open();
return connection;
}
}
Repository
public abstract class Repository<TEntity> where TEntity : new()
{
AdoNetContext _context;
public Repository(AdoNetContext context)
{
_context = context;
}
protected AdoNetContext Context { get; }
protected IEnumerable<TEntity> ToList(IDbCommand command)
{
using (var reader = command.ExecuteReader())
{
List<TEntity> items = new List<TEntity>();
while (reader.Read())
{
var item = new T();
Map(reader, item);
items.Add(item);
}
return items;
}
}
protected abstract void Map(IDataRecord record, TEntity entity);
}
EmployeeRepository
public class EmployeeRepository : Repository<Employee>
{
public EmployeeRepository(AdoNetContext context) : base(context)
{
}
public void Create(Employee employee)
{
using (var command = _connection.CreateCommand())
{
command.CommandText = @"INSERT INTO Employees (Name) VALUES(@name)";
command.AddParameter("name", employee.Name);
command.ExecuteNonQuery();
}
//todo: Get identity. Depends on the db engine.
}
public void Update(Employee employee)
{
using (var command = _connection.CreateCommand())
{
command.CommandText = @"UPDATE Employees SET Name = @name WHERE Id = @id";
command.AddParameter("name", employee.Name);
command.AddParameter("id", employee.Id);
command.ExecuteNonQuery();
}
}
public void Delete(int id)
{
using (var command = _connection.CreateCommand())
{
command.CommandText = @"DELETE FROM Employees WHERE Id = @id";
command.AddParameter("id", id);
command.ExecuteNonQuery();
}
}
public IEnumerable<Employee> FindUsers(string name)
{
using (var command = _connection.CreateCommand())
{
command.CommandText = @"SELECT * FROM Employees WHERE Name LIKE @name";
command.AddParameter("firstName", name + "%");
return ToList(command);
}
}
//public IEnumerable<Employee> FindBlocked()
//{
// using (var command = _connection.CreateCommand())
// {
// command.CommandText = @"SELECT * FROM Users WHERE Status = -1";
// return ToList(command);
// }
//}
protected override void Map(IDataRecord record, Employee employee)
{
employee.Name = (string)record["Name"];
employee.Id = (int)record["Id"];
}
}
And that should be the app
static void Main(string[] args)
{
// during app start
var factory = new AppConfigConnectionFactory("RepositoryPattern");
// during start of the current session
var context = new AdoNetContext();
// for the transaction
using (var uow = context.CreateUnitOfWork())
{
var repos1 = new EmployeeRepository(context);
var repos2 = new EmployeeRepository(context);
// do changes
// [...]
uow.SaveChanges();
}
}
But i am not getting it work! I get errors in two files:
It tells me that the AdoNetContext
has no parameter of type connectionFactory. I dont know what to add here.
And in the EmployeeRepository
file i get errors for
using (var command = _connection.CreateCommand())
What is here wrong? Maybe someone can explaing me what i am doing wrong!? This is driving me crazy!
Aucun commentaire:
Enregistrer un commentaire