views:

47

answers:

1

Right now I'm working my way thru the SportsStore exercise of Sanderson's "Pro ASP.Net MVC 2 Framework" book (page 107) and the exercise has me implementing a Repository pattern backed by a DB store using LINQ-to-SQL. I'm trying to figure out how to implement this same repository with the Subsonic ORM.

The basic repository code is as follows:

using System.Data.Linq;
namespace DomainModel.Concrete
{
    public class SqlProductsRepository : IProductsRepository
    {
        private Table<Product> productsTable;
        public SqlProductsRepository(string connectionString)
        {
            productsTable = 
                    (new DataContext(connectionString)).GetTable<Product>();
        }

        public IQueryable<Product> Products
        {
            get { return productsTable; }
        }
    }
}

The LINQ-To-SQL specific part of the code is the line involving DataContext and GetTable, I think.

Does Subsonic have a similar mechanism to this? If so,

  • what would the code look like?
  • would I be able to use the methods available in System.Data.Linq's Table like:
    • InsertOnSubmit()
    • Attach()
    • DeleteOnSubmit()
    • SubmitChanges()
    • etc.

UPDATE Got your message. Impressive Template, but I decided to try something simpler first:

using SubSonic.Repository;
namespace DomainModel.Concrete
{
    public class SqlProductsRepository : IProductsRepository
    {
        private SimpleRepository repo;
        private IQueryable<Product> products;
        public IQueryable<Product> Products
        {
            get { return products; }
        }

        public DbProductsRepository(string subsonicDatastore)
        {
            repo = new SimpleRepository(subsonicDatastore, SimpleRepositoryOptions.RunMigrations);
            this.Refresh();
        }

        public void SaveProduct(Product product) { SaveProduct(new List<Product>() { product }); }
        public void SaveProduct(IEnumerable<Product> productList)
        {
            var newProducts = from product in productList
                                 where product.ID == 0
                                 select product;
            var oldProducts = from product in productList
                                 where product.ID > 0
                                 select product;
            // If it's a new Product, just add it to the Repo
            repo.AddMany<Product>(newProducts);
            // If it's old, just update it.
            repo.UpdateMany<Product>(oldProducts);
            // Refresh internal list of products, in case table has changed.
            this.Refresh();
        }

        public void DeleteProduct(Product product) { DeleteProduct(new List<Product>() { product }); }
        public void DeleteProduct(IEnumerable<Product> productList)
        {
            repo.DeleteMany<Product>(productList);
            this.Refresh();
        }

        private void Refresh()
        {
            products = repo.All<Product>();
        }
    }
}

As far as I can tell, there is no drop-in replacement for DataContext, but there are other options that are just as easy.

I still plan on checking out your solution when I get more time. It seems more complex, but much more flexible/adaptable.

Thanks!

+1  A: 

Pretzel - we meet again :)

I use subsonic 3 but use it with the generic repository pattern. this means that i only have a single 'factory' for dishing out the entities. it looks a bit like this:

public class SubSonicRepository<T> : IRepository<T> where T : new()
{
    private readonly IQuerySurface _db;

    public SubSonicRepository()
        : this(SubsonicFrameworkObjectContextPerRequest.CurrentDatabase)
    {
    }

    public SubSonicRepository(IQuerySurface db)
    {
        _db = db ?? DB.CreateDB();
    }

    // lots of stuff omitted!!

    private IQueryable<T> GetAll()
    {
        var result = _db.GetQuery<T>();
        return result;
    }

    T IRepository<T>.GetByKey(object key)
    {
        ITable tbl = _db.FindTable(typeof(T).Name);

        var result = _db.Select.From(tbl)
                               .Where(tbl.PrimaryKey.Name).IsEqualTo(key)
                               .ExecuteSingle<T>();
        return result;
    }
}

... with lots of other code that follows. The _repository is instantiated in each controller (or service layer) and the scenario that you mention above happens in a slightly different way.

now, if i can get a copy of my T4 templates over to you, then you'd be able to follow it without my message by message rantings :)

jim
@Jim: Nice to see you again. ;) If you'd like to contact me, visit my website (in my SO profile) and then click on the "Contact Me" link and send me a message. Thanks!
Pretzel
message sent...
jim
msg received. checking out your code.
Pretzel
I did a quick basic instruction guide. full of holes but might just let you limp thro the process. i've emailed you the link...
jim