将泛型与实体一起使用

loc*_*ope 9 c# linq oop generics entity-framework

PersonBusiness.GetQuery方法中,PersonEntity遍及代码,并且有许多其他实体类型将类似地实现此方法.

我想在PersonBusiness中使用泛型参数来减少特定实体类型的使用,因为会有像其他实体一样的实现,我想阻止使用其他类型而不是预期的实体类型.但是通用参数使用版本无法成功或满足.

如果它更有意义,我也想使用接口而不是具体类.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Jef*_*son 5

尽管我对这篇文章发表了评论,但我想我会在这里写一个答案.由于我不了解用例,因此很难找到合适的解决方案.从来没有这里是代码

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

根据@Ivan Stoev的评论更新以使用DbSet支持Cast.

  • @lockedscope 您在评论中多次使用“类型推断”一词。但该术语适用于泛型方法,而这里您位于泛型类中。因此,所有方法都与类型“T”相关联,您**必须**在调用它们之前解析它们,例如,预期用法类似于“var pb = new PersonBusiness&lt;PersonEntity&gt;();” pb.GetQuery(...)`。因此,您的设计中不涉及类型推断。约束呢,它们确实允许您访问“T”的“Id”和“FullName”属性。接口和基类都可以工作。 (2认同)