Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository Pattern For Accessing Text File

I am fairly new to the Repository Pattern and I would like to do this correctly. I am also trying to make use of Inversion of Control (also new).

I would like to make sure I am using the repository pattern correctly.

I picked this up as an example of a base interface for my repositories.

public interface IRepository<T> where T : class
{
    IEnumerable<T> Find(Expression<Func<T, bool>> where);

    IEnumerable<T> GetAll();

    void Create(T p);

    void Update(T p);
}

IPaymentRepository is intended for extensions to IRepository (although I don't see why I would need this if I have the Find method above)

public interface IPaymentRepository : IRepository<Payment>
{
}

PaymentRepository simply reads a text file and builds a POCO.

public class PaymentRepository : IPaymentRepository
{
    #region Members

    private FileInfo paymentFile;
    private StreamReader reader;
    private List<Payment> payments;

    #endregion Members

    #region Constructors

    #endregion Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="PaymentRepository"/> class.
    /// </summary>
    /// <param name="paymentFile">The payment file.</param>
    public PaymentRepository(FileInfo paymentFile)
    {
        if (!paymentFile.Exists)
            throw new FileNotFoundException("Could not find the payment file to process.");

        this.paymentFile = paymentFile;
    }

    #region Properties

    #endregion Properties

    #region Methods

    public IEnumerable<Payment> Find(Expression<Func<Payment, bool>> where)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Gets all payments from payment file.
    /// </summary>
    /// <returns>Collection of payment objects.</returns>
    public IEnumerable<Payment> GetAll()
    {
        this.reader = new StreamReader(this.paymentFile.FullName);
        this.payments = new List<Payment>();

        while (!reader.EndOfStream)
        {
            string line = reader.ReadLine();
            Payment payment = new Payment()
            {
                AccountNo = line.Substring(0, 11),
                Amount = double.Parse(line.Substring(11, 10))
            };

            this.payments.Add(payment);
        }

        return this.payments;
    }

    public void Create(Payment p)
    {
        throw new NotImplementedException();
    }

    public void Update(Payment p)
    {
        throw new NotImplementedException();
    }

    #endregion Methods

I would like to know how to implement the Find method. I am assuming I would call GetAll and build an internal cache to the repository. For example, I would like to find all accounts that have payments greater than $50.

like image 405
Novus Avatar asked Nov 04 '22 10:11

Novus


1 Answers

With your current IRepository signature you would implement it like this:

public IEnumerable<Payment> Find(Expression<Func<Payment, bool>> where)
{
    this.reader = new StreamReader(this.paymentFile.FullName);
    this.payments = new List<Payment>();

    while (!reader.EndOfStream)
    {
        string line = reader.ReadLine();
        Payment payment = new Payment()
        {
            AccountNo = line.Substring(0, 11),
            Amount = double.Parse(line.Substring(11, 10))
        };
        if (where(payment) 
        {
           this.payments.Add(payment);
        }
    }

    return this.payments;
}

However, If your system memory allows it, you could keep a cached list (from GetAll()) and use Find() on the list. This should be an order of magnitude faster depending on the size of your list.

like image 126
Bas Avatar answered Nov 09 '22 15:11

Bas