c# - 如何动态构建 Entity Framework 查询?

标签 c# linq entity-framework filter filtering

我是 Entity Framework 的新手,我有一个关于过滤数据的问题。

我有两个不同的日志实体,它们是:DiskLogNetworkLog .这些实体都来自 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 工作。我那里有几种执行方式:

  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<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/

相关文章:

c# - 两个(未排序的)数据表之间匹配的优化算法?

c# - 使用 Contains 搜索部分 linq 文本

c# - DbGeometry 使有效?

C# - 如何使用 lambda 在 Entity Framework 中执行简单查询?

c# - 枚举的显示文本

c# - Visual Studio 2010 EXE 打包

c# - 如何改进缺少右大括号的 Sprache 解析器错误消息?

c# - 属性不起作用的 LINQ RemoveAll

c# - 为此关系配置一个非影子主键

c# - 您是否将存储库模式与 Entity Framework 一起使用?