我是 Entity Framework 的新手,我有一个关于过滤数据的问题。
我有两个不同的日志实体,它们是: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 工作。我那里有几种执行方式:
if logType == LogType.Disk && computerId <= 0
(意思是查询时不需要使用computerId参数,只选择DiskLog实体)if logType == LogType.Disk && computerId > 0
(意味着我必须使用 computerId 参数,仅选择 DiskLog 实体)if logType == LogType.NotInitialized && computerId <= 0
(不需要使用computerId和logType,只需要选择所有实体,DiskLog和NetworkLog)if logType == LogType.NotInitialized && computerId > 0
(选择指定计算机的所有类型的日志)if logType == LogType.Network && computerId <= 0
(选择所有 NetworkLog 实体)if 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;
我建议在没有值的情况下使用可空值类型。
关于c# - 如何动态构建 Entity Framework 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5881107/