views:

711

answers:

1

Hi Experts, I am working on a similar project like NerdDinner (www.nerddinner.com). I have similar tables, but I have used a generic repository (copied from here http://www.codeproject.com/KB/architecture/linqrepository.aspx). It seems working without any problem. Here are the codes.


IRepository.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Linq;
using System.Linq;

namespace Listing.Repository
{

    public interface IRepository<T> where T : class
    {
        /// <summary>
        /// Return all instances of type T.
        /// </summary>
        /// <returns></returns>
        IEnumerable<T> GetAllRows();

        /// <summary>
        /// Return all instances of type T that match the expression exp.
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        IEnumerable<T> GetAllRowsWhere(Func<T, bool> exp);


        /// <summary>Returns the single entity matching the expression. Throws an exception if there is not exactly one such entity.</summary>
        /// <param name="exp"></param><returns></returns>
        T Single(Func<T, bool> exp);

        /// <summary>Returns the first element satisfying the condition.</summary>
        /// <param name="exp"></param><returns></returns>
        T First(Func<T, bool> exp);

        /// <summary>
        /// Mark an entity to be deleted when the context is saved.
        /// </summary>
        /// <param name="entity"></param>
        void Delete(T entity);

        /// <summary>
        /// Adds new entity..
        /// </summary>
        /// <param name="entity"></param>
        void Insert(T entity);



        void Update(T entity);

        /// <summary>
        /// Create a new instance of type T.
        /// </summary>
        /// <returns></returns>
        T New();

        /// <summary>Persist the data context.</summary>
        void SaveAll();
    }
}


Repository.cs

using System;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;

namespace Listing.Repository
{
    public class Repository<T> : IRepository<T>
        where T : class
    {
        protected Listing.Data.IDataContextFactory _dataContextFactory;

        /// <summary>
        /// Return all instances of type T.
        /// </summary>
        /// <returns></returns>


        public IEnumerable<T> GetAllRows()
        {
            return GetTable;
        }
        /// <summary>
        /// Return all instances of type T that match the expression exp.
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IEnumerable<T> GetAllRowsWhere(Func<T, bool> exp)
        {
            return GetTable.Where<T>(exp);
        }

        /// <summary>See _vertexRepository.</summary>
        /// <param name="exp"></param><returns></returns>
        public T Single(Func<T, bool> exp)
        {
            return GetTable.SingleOrDefault(exp);
        }

        /// <summary>See _vertexRepository.</summary>
        /// <param name="exp"></param><returns></returns>
        public T First(Func<T, bool> exp)
        {
            return GetTable.First(exp);
        }

        /// <summary>See _vertexRepository.</summary>
        /// <param name="entity"></param>
        public virtual void Delete(T entity)
        {
            _dataContextFactory.Context.GetTable<T>().DeleteOnSubmit(entity);
        }

        /// <summary>
        /// Create a new instance of type T.
        /// </summary>
        /// <returns></returns>
        public virtual T New()
        {
            T entity = Activator.CreateInstance<T>();
            GetTable.InsertOnSubmit(entity);
            return entity;
        }



        /// <summary>
        /// Adds an insance T.
        /// </summary>
        /// <returns></returns>
        public virtual void Insert(T entity)
        {
            GetTable.InsertOnSubmit(entity);
        }

        /// <summary>
        /// Update entity.
        /// </summary>
        /// <returns></returns>
        public virtual void Update(T entity)
        {
            _dataContextFactory.Context.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, entity);
        }

        /// <summary>See _vertexRepository.</summary>
        public void SaveAll()
        {
            _dataContextFactory.SaveAll();
        }

        public Repository(Listing.Data.IDataContextFactory dataContextFactory)
        {
            _dataContextFactory = dataContextFactory;
        }

        #region Properties

        private string PrimaryKeyName
        {
            get { return TableMetadata.RowType.IdentityMembers[0].Name; }
        }

        private System.Data.Linq.Table<T> GetTable
        {
            get { return _dataContextFactory.Context.GetTable<T>(); }
        }

        private System.Data.Linq.Mapping.MetaTable TableMetadata
        {
            get { return _dataContextFactory.Context.Mapping.GetTable(typeof(T)); }
        }

        private System.Data.Linq.Mapping.MetaType ClassMetadata
        {
            get { return _dataContextFactory.Context.Mapping.GetMetaType(typeof(T)); }
        }

        #endregion
    }
}


IDataContext.cs

using System;
using System.Linq;

namespace Listing.Data
{
    public interface IDataContextFactory
    {
        System.Data.Linq.DataContext Context { get; }
        void SaveAll();
    }


    public class DataContext : IDataContextFactory
    {


        #region IDataContextFactory Members

        private System.Data.Linq.DataContext dt;

        public System.Data.Linq.DataContext Context
        {
            get
            {
                if (dt == null)
                    dt = new Listing.Data.ListingDataContext();
                return dt;
            }
        }

        public void SaveAll()
        {
            dt.SubmitChanges();
        }

        #endregion
    }
}


Now I am in a stage where I have dropped a two functions DistanceBetween and NearestDinners(mine one's name is different), to my dbml file. I want to use these functions to do some calculation.

Here are the codes used in nerddinner project

public IQueryable<Dinner> FindByLocation(float latitude, float longitude) {
    var dinners = from dinner in FindUpcomingDinners()
                  join i in db.NearestDinners(latitude, longitude) 
                  on dinner.DinnerID equals i.DinnerID
                  select dinner;

    return dinners;
}

How would I achieve similar with my generic Repository. Help will be appreciated.

Regards Paraminder

A: 

You could use an extension method?

public static IQueryable<Dinner> FindByLocation(this IQueryable<Dinner>, float latitude, float longitude) {
    var dinners = from dinner in this
                  join i in this(latitude, longitude) 
                  on dinner.DinnerID equals i.DinnerID
                  select dinner;

    return dinners;
}
bleevo
but the context doesnt have any idea about the function.
Parminder
it does not need to, the context has linked to the `IQueryable<Dinner>` which is passed in as a param
cottsak