2017-05-03 51 views
9

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); 
    } 
} 
+1

究竟是什麼問題,你有? – mclark1129

+0

它不編譯,不相容性的IQueryable 和IQueryable的之間。鑄造可以解決它,但在這種情況下有很多鑄件,因此它有氣味。我認爲它應該有不同的設計。 – lockedscope

+0

你的文章的標題是通用的。 – niksofteng

回答

5

儘管我在文章發表的留言,我想我應該把答案在這裏它編譯。由於我不明白用例,所以很難推理出適當的解決方案。從未在少在這裏更新有利於演員的使用​​DbSet代碼

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); 
    } 
} 

,每從@Ivan Stoev評論。

+1

@lockedscope您在評論中多次使用單詞*類型推斷*。但是這個術語適用於泛型方法,而在這裏你是在一個泛型類中。因此,所有的方法都與類型'T'相關聯,您可以在調用它們之前解析它們**,例如,預期的用法類似於'var pb = new PersonBusiness (); pb.GetQuery(...)'。所以在你的設計中沒有涉及類型推斷。約束條件是什麼?它們**允許你訪問'T'的'Id'和'FullName'屬性。接口和基類都可以工作。 –

+1

所以Jeffrey的代碼肯定會編譯(如果它是你之後的,這是另一個故事,這是從你的問題來看還不清楚)。我建議的唯一改變是使用'DbSet ()'而不是'Db.PersonSet.Cast ()'。 –

+0

對不起,我混淆了事情,它實際上編譯。 – lockedscope

0

我將PersonEntity拖出界面並使用類型約束來要求T實現IPersonEntity。我沒有看到你在做什麼,但你似乎想要使用類型約束,並且之前沒有聽說過它們。

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; 
    } 
} 
+0

它不編譯,因爲約束不用於類型推斷 – lockedscope

+0

我其實沒有嘗試編譯代碼。當你不使用類型推斷時它有效嗎? – user2023861

+0

它不編譯。 – lockedscope

0

由於戴意見。這種方法打破了存儲庫模式我的解決方案是完全建立一個通用存儲庫作爲朱莉在勒曼ef architecture

與模式實現一個帖子是ef-code-first-you-on-repository

解釋這段代碼可以幫助。

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(); 
     } 
    }