1
\$\begingroup\$

Continuation of this question: Unit of Work with Generic Repository Pattern MVVM

I have made some modifications:

  • Interfaces aren't forced to implement IDisposable
  • Removed the finalizers
  • Rebuilt UoW

FeedRepository:

internal class FeedRepository<T> : IFeedRepository<T>, IDisposable 
    where T: IBaseFeed, new()
{
    private readonly SQLiteConnection _db;
    private IList<T> _feeds;

    private bool _isDisposed = false;

    public int Count
    {
        get
        {
            return _feeds.Count;
        }
    }

    public FeedRepository(SQLiteConnection db)
    {
        this._db = db;
        this._feeds = _db.Table<T>().ToList();
    }

    public void Add(T feed)
    {
        this._feeds.Add(feed);
        this._db.Insert(feed);
    }

    public IEnumerable<T> GetAll()
    {
        return this._feeds;
    }

    public T GetFeedById(int id)
    {
        return this._feeds.Where(feed => int.Equals(feed.Id, id)).Single();
    }

    public T GetFeedByLink(string feedLink)
    {
        return this.GetFeedByLink(new Uri(feedLink));
    }

    public T GetFeedByLink(Uri feedLink)
    {
        return this._feeds.Where(feed => Uri.Equals(feed.Link, feedLink)).Single();
    }

    public int GetFeedIdByLink(string feedLink)
    {
        return this.GetFeedIdByLink(new Uri(feedLink));
    }

    public int GetFeedIdByLink(Uri feedLink)
    {
        return this._feeds.Where(feed => Uri.Equals(feed.Link, feedLink)).Select(feed => feed.Id).Single();
    }

    public void Remove(T feed)
    {
        this._feeds.Remove(feed);
        this._db.Delete(feed);
    }

    public void RemoveById(int id)
    {
        this.Remove(this.GetFeedById(id));
    }

    public void Update(T feed)
    {
        int indexOfFeed = this._feeds.IndexOf(this.GetFeedById(feed.Id));
        this._feeds[indexOfFeed] = feed;

        this._db.Update(feed);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool isDisposing)
    {
        if (!this._isDisposed)
        {
            if (isDisposing)
            {
                if (this._db != null)
                {
                    this._db.Dispose();
                }
            }

            this._isDisposed = true;
        }
    }
}

IUnitOfWork:

internal interface IUnitOfWork
{
    void Commit();
    void Rollback();
}

UnitOfWork:

internal class UnitOfWork : IUnitOfWork, IDisposable
{
    private readonly SQLiteConnection _db;

    private FeedRepository<FeedData> _feedDataRepository;
    private FeedRepository<FeedItem> _feedItemRepository;

    private bool _isDisposed = false;

    public FeedRepository<FeedData> FeedDataRepository
    {
        get
        {
            return _feedDataRepository;
        }
        set
        {
            _feedDataRepository = value;
        }
    }

    public FeedRepository<FeedItem> FeedItemRepository
    {
        get
        {
            return _feedItemRepository;
        }
        set
        {
            _feedItemRepository = value;
        }
    }

    public UnitOfWork(SQLiteConnection db)
    {
        this._db = db;
        this._feedDataRepository = new FeedRepository<FeedData>(this._db);
        this._feedItemRepository = new FeedRepository<FeedItem>(this._db);

        this._db.BeginTransaction();
    }

    public void Commit()
    {
        this._db.Commit();
    }

    public void Rollback()
    {
        this._db.Rollback();
    }

    protected virtual void Dispose(bool isDisposing)
    {
        if (!this._isDisposed)
        {
            if (isDisposing)
            {
                if (this._db != null)
                {
                    this._db.Dispose();   
                }
            }

            this._isDisposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Unfortunately, I still have no idea how to remove this._feeds = _db.Table<T>().ToList(); from the repository, because when I delete it, I can't use GetAll(), GetFeedById() and so on.

Edit

That's IBaseFeed:

public interface IBaseFeed
{
    int Id { get; set; }
    string Title { get; set; }
    DateTime PubDate { get; set; }
    Uri Link { get; set; }
    string Misc { get; set; }
}

If I don't use IBaseFeed I won't take advantage of using:

    public T GetFeedByLink(Uri feedLink)
    {
        return this._feeds.Where(feed => Uri.Equals(feed.Link, feedLink)).Single();
    }

due to any of following properties such as 'Id' or 'Link'. That' why I'd rather use IRepository<T> where T : class and IFeedRepository<T> where T : class, IBaseFeed.

I have been writing an app for Windows 8.1 and unluckily EF is not available. The only wrapper for SQLite that I found is sqlite-net.

sqlite-net doesn't contain method LastInsertId so I have no idea how to return T with the database-generated ID?

\$\endgroup\$
  • 1
    \$\begingroup\$ If SQLite-net works like EF, then you don't need a LastInsertId method - it should just update your POCO automagically :) \$\endgroup\$ – Mathieu Guindon Dec 4 '13 at 20:50
2
\$\begingroup\$

This new code looks much more cohesive, well done!

this._feeds = _db.Table<T>().ToList();

This is eager-loading the table content into your repository class, whenever you instantiate it. What you want is lazy-loading, and that's a different ball game - I mean, I would rely on an object/relational mapper like to do that gruntwork for me. There must be an EF provider for sqlite, for sure.


Something about your repository interface IFeedRepository<T>, is bothering me. Based on your previous post and this updated code, I believe your interface now looks like this:

internal interface IFeedRepository<T> where T : IBaseFeed
{
    int Count { get; }

    void Add(T feed);
    IEnumerable<T> GetAll();
    T GetFeedById(int id);
    T GetFeedByLink(string feedLink);
    T GetFeedByLink(Uri feedLink);
    int GetFeedIdByLink(string feedLink);
    int GetFeedIdByLink(Uri feedLink);
    void Remove(T feed);
    void RemoveById(int id);
    void Update(T feed);
}

I think you're missing an opportunity at a generic repository here:

internal interface IRepository<T> where T : class
{
    int Count { get; }
    T GetById(int it);
    IEnumerable<T> GetAll();
    void Add(T entity);
    void Remove(T entity);
    void RemoveById(int id);
    void Update(T entity);
}

And then you could have IFeedRepository<T> : IRepository<T> where T : class (I'm not sure what IBaseFeed is, but it looks like a superfluous interface), and you can reuse your IRepository<T> interface for other "entities".

Just noticed you have Add(T) returning void - wouldn't it be practical if it returned a T with the database-generated ID?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.