如何动态构建entity framework查询?

我对Entity Framework很新,我对过滤数据有疑问。

我有两个不同的Log实体,它们是: DiskLogNetworkLog 。 这些实体都是从Log实体派生的。 以下是我的C#应用​​程序中的一些代码:

 public class Log { ... } public class DiskLog : Log { ... } public class NetworkLog : Log { ... } public enum LogType { NotInitialized = 0, Disk, Network } public List GetWithFilter( Guid userKey, int nSkip, int nTake, DateTime dateFrom = DateTime.MinValue, DateTime dateTo = DateTime.MaxValue, LogType logType = LogType.NotInitialized, int computerId = 0) { // need to know how to optimize ... return ... } 

当然,我已经创建了工作应用程序和数据库表。 我想要做的是使函数GetWithFilter工作。 我有几种执行方式:

  1. if logType == LogType.Disk && computerId <= 0 (这意味着查询中不需要使用computerId参数,只选择DiskLog实体)

  2. if logType == LogType.Disk && computerId > 0 (意味着我必须使用computerId参数,请仅选择DiskLog实体)

  3. if logType == LogType.NotInitialized && computerId <= 0 (不需要使用computerId和logType,只需选择所有实体,DiskLog和NetworkLog)

  4. if logType == LogType.NotInitialized && computerId > 0 (为指定的计算机选择所有类型的日志)

  5. if logType == LogType.Network && computerId <= 0 (选择所有NetworkLog实体)

  6. if logType == LogType.Network && computerId > 0 (为指定的计算机选择所有NetworkLog实体)

如您所见,有很多可用的选项。 我要编写6个这样的查询:

1。

 context.LogSet .OfType .Where(x => x.Computer.User.UserKey == userKey) .Where(x => x.DateStamp >= dateFrom && x.DateStamp  x.Id) .Skip(nSkip) .Take(nTake) .ToList(); 

2。

 context.LogSet .OfType .Where(x => x.Computer.User.UserKey == userKey) .Where(x => x.DateStamp >= dateFrom && x.DateStamp  x.Computer.Id == computerId) .OrderByDescending(x => x.Id) .Skip(nSkip) .Take(nTake) .ToList(); 

3。

 context.LogSet .Where(x => x.Computer.User.UserKey == userKey) .Where(x => x.DateStamp >= dateFrom && x.DateStamp  x.Id) .Skip(nSkip) .Take(nTake) .ToList(); // simplest one! 

4。

 context.LogSet .Where(x => x.Computer.User.UserKey == userKey) .Where(x => x.DateStamp >= dateFrom && x.DateStamp  x.Computer.Id == computerId) .OrderByDescending(x => x.Id) .Skip(nSkip) .Take(nTake) .ToList(); 

5。

 context.LogSet .OfType .Where(x => x.Computer.User.UserKey == userKey) .Where(x => x.DateStamp >= dateFrom && x.DateStamp  x.Id) .Skip(nSkip) .Take(nTake) .ToList(); 

6。

 context.LogSet .OfType .Where(x => x.Computer.User.UserKey == userKey) .Where(x => x.DateStamp >= dateFrom && x.DateStamp  x.Computer.Id == computerId) .OrderByDescending(x => x.Id) .Skip(nSkip) .Take(nTake) .ToList(); 

所以问题是如何优化代码? 如何让它变得更好。

您可以轻松使用查询组合。

首先从查询开始。

 IQueryable query = context.LogSet; 

他们组成子查询。

 if (logType == LogType.Disk) { query = query.OfType(); // not sure if you need conversion here } else if (logType == LogType.Network) { query = query.OfType(); // not sure if you need conversion here } query = query.Where(x => x.Computer.User.UserKey == userKey); if (computerId != 0) query = query.Where( x => x.Computer.Id == computerId); // .. and so on query = query.OrderByDescending(x => x.Id).Skip(nSkip).Take(nTake); return query.ToList(); // do database call, materialize the data and return; 

当没有值时,我会建议使用可空值的类型作为案例。

您可以使用Func来优化它

 IEnumerable Select(IEnumerable source, Func userKeyFunc, Func dateFunc, int skip, int take) { return source.OfType().Where(userKeyFunc).Where(dateFunc).Skip(skip).Take(take); } 

然后使用:

 var result = Select(context.LogSet,x => x.Computer.User.UserKey == userKey, x => x.DateStamp >= dateFrom && x.DateStamp < dateTo, nSkip,nTake) 

您可以为此function创建工厂