我对Entity Framework很新,我有一个关于过滤数据的问题.
我有两个Log实体,分别是:DiskLog和NetworkLog.这些实体都来自于Log实体.这是我的C#应用程序的一些代码:
- public class Log { ... }
- public class DiskLog : Log { ... }
- public class NetworkLog : Log { ... }
- public enum LogType
- {
- NotInitialized = 0,Disk,Network
- }
- public List<Log> 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工作.我有几种执行方式:
>如果logType == LogType.Disk&&& computerId <= 0(这意味着查询中不需要使用computerId参数,仅选择DiskLog实体)
>如果logType == LogType.Disk&&& computerId> 0(意味着我必须使用computerId参数,仅选择DiskLog实体)
>如果logType == LogType.NotInitialized&& computerId <= 0(不需要使用computerId和logType,只需选择所有实体,DiskLog和NetworkLog)
>如果logType == LogType.NotInitialized&& computerId> 0(选择指定计算机的所有类型的日志)
>如果logType == LogType.Network&& computerId <= 0(选择所有NetworkLog实体)
>如果logType == LogType.Network&& computerId> 0(选择指定计算机的所有NetworkLog实体)
你可以看到,有很多可用的选项.而且我写了6个这样的查询:
1.
- context.LogSet
- .OfType<DiskLog>
- .Where(x => x.Computer.User.UserKey == userKey)
- .Where(x => x.DateStamp >= dateFrom && x.DateStamp < dateTo)
- .OrderByDescending(x => x.Id)
- .Skip(nSkip)
- .Take(nTake)
- .ToList();
2.
- context.LogSet
- .OfType<DiskLog>
- .Where(x => x.Computer.User.UserKey == userKey)
- .Where(x => x.DateStamp >= dateFrom && x.DateStamp < dateTo)
- .Where(x => 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 < dateTo)
- .OrderByDescending(x => 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 < dateTo)
- .Where( x => x.Computer.Id == computerId)
- .OrderByDescending(x => x.Id)
- .Skip(nSkip)
- .Take(nTake)
- .ToList();
5.
- context.LogSet
- .OfType<NetworkLog>
- .Where(x => x.Computer.User.UserKey == userKey)
- .Where(x => x.DateStamp >= dateFrom && x.DateStamp < dateTo)
- .OrderByDescending(x => x.Id)
- .Skip(nSkip)
- .Take(nTake)
- .ToList();
6.
- context.LogSet
- .OfType<NetworkLog>
- .Where(x => x.Computer.User.UserKey == userKey)
- .Where(x => x.DateStamp >= dateFrom && x.DateStamp < dateTo)
- .Where( x => x.Computer.Id == computerId)
- .OrderByDescending(x => x.Id)
- .Skip(nSkip)
- .Take(nTake)
- .ToList();
那么问题是如何优化代码?在哪里可以使它更好.
解决方法
您可以轻松使用查询编译.
你首先从查询开始.
- IQueryable<Log> query = context.LogSet;
他们组成子查询.
- if (logType == LogType.Disk)
- {
- query = query.OfType<DiskLog>(); // not sure if you need conversion here
- }
- else if (logType == LogType.Network)
- {
- query = query.OfType<NetworkLog>(); // 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;
而当没有值时,我会推荐使用可空值类型.