Reputation: 983
In PersonBusiness.GetQuery
method, the PersonEntity
is peppered all over code and there are a lot of other entity types that will implement this method similarly.
I want to use generic parameters in PersonBusiness to lessen usage of specific entity type because there will be implementations like this one with other entities and i want to prevent some other type used instead of the intended entity type. But could not be successful or satisfied by generic parameter used versions.
I also want to use interfaces instead of concrete classes if it is more meaningful.
public class Entities: DbContext
{
public virtual DbSet<PersonEntity> PersonSet { get; set; }
}
public class PersonEntity
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class BaseBusiness
{
public Entities Db => new Entities();
}
public abstract class BaseBusiness<T> : BaseBusiness where T : class
{
public IQueryable<T> GetQuery<TKey>(Expression<Func<T, bool>> where,
Expression<Func<T, TKey>> orderBy)
{
IQueryable<T> query = Db.Set<T>();
if (where != null)
query = query.Where(where);
if (orderBy != null)
query = query.OrderBy(orderBy);
return query;
}
public abstract IQueryable<T> ApplyDefaultOrderyBy(IQueryable<T> query);
public IQueryable<T> GetQuery(IQueryable<T> query, string orderBy, Func<IQueryable<T>, IQueryable<T>> defaultOrderBy = null)
{
if (orderBy != null)
query = query.OrderBy(orderBy);
else
query = defaultOrderBy != null ? defaultOrderBy(query) : ApplyDefaultOrderyBy(query);
return query;
}
}
public class PersonBusiness : BaseBusiness<PersonEntity>
{
public IQueryable<PersonEntity> GetQuery(string orderBy, int? groupId)
{
IQueryable<PersonEntity> query = Db.PersonSet;
Func<IQueryable<PersonEntity>, IQueryable<PersonEntity>> defaultOrderBy = null;
if (groupId.HasValue)
{
query = query.Where(d => d.Id == groupId);
}
else
{
defaultOrderBy = q => q.OrderBy(d => d.Id).ThenBy(d => d.FullName);
}
return GetQuery(query, orderBy, defaultOrderBy);
}
public override IQueryable<PersonEntity> ApplyDefaultOrderyBy(IQueryable<PersonEntity> query)
{
return query.OrderBy(q => q.FullName);
}
}
Upvotes: 9
Views: 1392
Reputation: 586
As Dai comments. This approach breaks repository pattern. My solution is create an Generic Repository exactly as Julie Lerman explain in ef architecture
A post with the pattern implementation is in ef-code-first-you-on-repository
This snippet could help.
public abstract class BaseRepository<T> : IBaseRepository<T> where T : class
{
public DbContext Context { get; protected set; }
public BaseRepository()
{
this.Context = new AppDbContext();
}
public BaseRepository(AppDbContext context)
{
this.Context = context;
}
public IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
var query = Context.Set<T>().AsQueryable();
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public DbEntityEntry<T> Entry(T entity)
{
return this.Context.Entry(entity);
}
public virtual void InsertOrUpdate(params T[] entities)
{
foreach (var entity in entities)
{
this.Context.Entry(entity).State = EntityState.Added;
}
}
public void SaveChanges()
{
this.Context.SetCurrentStateToEntities();
this.Context.SaveChanges();
this.Context.SetToUndefined();
}
}
Upvotes: 0
Reputation: 2562
Despite my comment on the post, I figured I'd put an answer up here which compiles. As I don't understand the use case, it's hard to reason about a proper solution. Never-the-less here is the code
public class PersonBusiness<T> : BaseBusiness<T> where T: PersonEntity
{
public IQueryable<T> GetQuery(string orderBy, int? groupId)
{
IQueryable<T> query = Db.Set<T>();
Func<IQueryable<T>, IQueryable<T>> defaultOrderBy = null;
if (groupId.HasValue)
{
query = query.Where(d => d.Id == groupId);
}
else
{
defaultOrderBy = q => q.OrderBy(d => d.Id).ThenBy(d => d.FullName);
}
return GetQuery(query, orderBy, defaultOrderBy);
}
public override IQueryable<T> ApplyDefaultOrderyBy(IQueryable<T> query)
{
return query.OrderBy(q => q.FullName);
}
}
Updated to use DbSet in favor of Cast, per the comment from @Ivan Stoev.
Upvotes: 5
Reputation: 8208
I pulled out PersonEntity into an interface and used a type constraint to require that T implement IPersonEntity. I don't see the point of what you're doing, but it seems like you want to use type constraints and just haven't heard of them before.
https://msdn.microsoft.com/en-us/library/d5x73970.aspx
public interface IPersonEntity
{
int Id { get; set; }
string FullName { get; set; }
}
public class PersonBusiness<T> where T : IPersonEntity
{
public IQueryable<T> GetQuery(string orderBy, int? groupId)
{
IQueryable<T> query = Db.PersonSet;
Func<IQueryable<T>, IQueryable<T>> defaultOrderBy = null;
if (groupId.HasValue)
{
query = query.Where(d => d.Id == groupId);
}
else
{
defaultOrderBy = q => q.OrderBy(d => d.Id).ThenBy(d => d.FullName);
}
return GetQuery(query, orderBy, defaultOrderBy);
}
public IQueryable<T> ApplyDefaultOrderyBy(IQueryable<T> query)
{
return query.OrderBy(q => q.FullName);
}
public IQueryable<T> GetQuery(IQueryable<T> query, string orderBy, Func<IQueryable<T>, IQueryable<T>> defaultOrderBy = null)
{
if (orderBy != null)
query = query.OrderBy(orderBy);
else
query = defaultOrderBy != null ? defaultOrderBy(query) : ApplyDefaultOrderyBy(query);
return query;
}
}
Upvotes: 0