2

I have a generic repository an I am trying to add a GetById method as shown here C# LINQ to SQL: Refactoring this Generic GetByID method

The problem is my repository does not use System.Data.Linq.DataContext instead I use System.Data.Entity.DbContext

So I get errors where I try to use

Mapping.GetMetaType

and

return _set.Where( whereExpression).Single();

How can I implement a generic GetById method in CTP5? Should I be using System.Data.Entity.DbContext in my Repository.

Here is the start of my repository class

  public class BaseRepository<T> where T : class
    {

        private DbContext _context;
        private readonly DbSet<T> _set;

        public BaseRepository()
        {
            _context = new MyDBContext();
            _set = _context.Set<T>();

        }
Community
  • 1
  • 1
Daveo
  • 19,018
  • 10
  • 48
  • 71

2 Answers2

11

The most basic approach is simply

public T GetById(params object[] keys)
{
  _set.Find(keys);
}

If you know that all your entities have primary key called Id (it doesn't have to be called Id in DB but it must be mapped to property Id) of defined type you can use simply this:

public interface IEntity
{
  int Id { get; }
}

public class BaseRepository<T> where T : class, IEntity
{
  ...

  public T GetById(int id)
  {
    _set.Find(id);
  }
}

If data type is not always the same you can use:

public interface IEntity<TKey>
{
  TKey Id { get; }
}

public class BaseRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>
{
  ...

  public TEntity GetById(TKey id)
  {
    _set.Find(id);
  }
}

You can also simply use:

public class BaseRepository<TEntity, TKey> where TEntity : class
{
  ...

  public TEntity GetById(TKey id)
  {
    _set.Find(id);
  }
}
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Excellent, thanks for explaining the many approaches. They all seem to work fine apart from _set.FindBy I cannot find this method on System.Data.Entity.DBSet – Daveo Mar 02 '11 at 21:08
  • It is typo :) It should be `Find` – Ladislav Mrnka Mar 02 '11 at 21:23
  • @Ladislav Mrnka: In your first example, where you supply params object[] keys to the GetById method, In case there are 2 fields as primary keys, how do you map in Find each key to the relevant field? – Naor Apr 25 '11 at 21:58
  • @Noar: `Find` in DbContext API (EFv4.1) simply accept `params object[]` so you only have to send parameters in correct order defined on the entity. – Ladislav Mrnka Apr 25 '11 at 22:15
  • @Ladislav Mrnka: How the Find knows which object is for which key? – Naor Apr 25 '11 at 22:57
  • @Naor: `Find` uses the order of parameters because order of key members must be defined. – Ladislav Mrnka Apr 26 '11 at 18:49
  • @Ladislav Mrnka: Where does this order defined? Can I change it? – Naor Apr 26 '11 at 19:35
  • @Naor: The order is defined in mapping either by fluent API, data annotations or in EDMX. – Ladislav Mrnka Apr 26 '11 at 19:41
  • @LadislavMrnka Hi, i am trying (or struggling) to make something similar with more control on the id so i was wondering in the last exemple TEntity GetById if we could use x => x.Id.Equals(id) taking into consideration TEntity is a Entity type generic that expose a TKey Id { get; set; } ? since i use the objectcontext and not the dbcontext. – Rushino Jan 12 '12 at 14:46
1

try this

    public virtual T GetByID(object id)
    {

        // Define the entity key values.
        IEnumerable<KeyValuePair<string, object>> entityKeyValues =
            new KeyValuePair<string, object>[] { 
            new KeyValuePair<string, object>("Id", id) };

        string qualifiedEntitySetName = _context.DefaultContainerName + "." + typeof(T).Name;
        EntityKey key = new EntityKey(qualifiedEntitySetName, entityKeyValues);

        return (T)_context.GetObjectByKey(key);           
    }
mamun
  • 51
  • 1
  • 5