0

我正在尝试使用实体框架重构繁琐的 LINQ-to-SQL 数据层。模型背后的数据库架构很大,一个典型的查询可能有 20 到 30 个包含。EF 会为此类查询生成大量 SQL 语句,迄今为止最大的是 4k 行,但它们仍然可以及时执行,所以这不是问题。

问题是 EF 需要很长时间,最多需要 4 或 5 秒来生成查询。为了克服这个问题,我使用了 CompileQuery。那么问题是现有的 L2S 数据层有很多过滤器可以根据用户输入应用于查询。这些过滤器中的单个值需要在运行时设置。

下面的代码不起作用,因为初始静态值被编译到查询中,但它演示了我正在尝试做的事情。

public static class DataLayer
{
    static Func<MyEntities, int, IQueryable<Prescription>> compiledQuery;

    static int? FilterHpID;
    static Expression<Func<Prescription, bool>> filter1 = x => (FilterHpID == null || x.Prescriber.HPID == FilterHpID);

    static DateTime? FilterDateTime;
    static Expression<Func<Prescription, bool>> filter2 = x => (FilterDateTime == null || x.DateTimeDispensed > FilterDateTime);

    public static List<Prescription> Get(int patientID, int? hpID, DateTime? dispensed)
    {
        FilterHpID = hpID;
        FilterDateTime = dispensed;

        if (compiledQuery == null)
        {
            compiledQuery = System.Data.Objects.CompiledQuery.Compile((MyEntities entities, int id) =>
                        (from pre in entities.Prescription
                         where pre.PatientID == id
                         select pre)
                         .Where(filter1)
                         .Where(filter2));
        }

        using (MyEntities entities = new MyEntities())
        {
            return compiledQuery(entities, patientID).ToList();
        }
    }
}

有什么方法可以在编译的查询中包含我的过滤器表达式,并且能够在执行查询时在过滤器表达式上设置值?

4

2 回答 2

0

过滤器必须是编译查询的一部分,之后您可以在调用查询时设置它们。我认为你可以使用类似的东西:

public static IQueryable<Prescription> Filter1(this IQueryale<Prescription> query, 
    DateTime? param)
{
    return query.Where(x => (param == null || x.Prescriber.HPID == param));
}

然后,您应该能够将编译后的查询定义为:

 compiledQuery = System.Data.Objects.CompiledQuery
                       .Compile((MyEntities entities, int id, DateTime? param) =>
                           (from pre in entities.Prescription
                            where pre.PatientID == id
                            select pre)
                           .Filter1(param));

它适用于普通查询,但我从未在编译查询中尝试过。如果它不起作用,您必须将过滤器表达式直接放在已编译的查询中:

 compiledQuery = System.Data.Objects.CompiledQuery
                       .Compile((MyEntities entities, int id, DateTime? param) =>
                           (from pre in entities.Prescription
                            where pre.PatientID == id
                            select pre)
                           .Where(x => (param == null || x.Prescriber.HPID == param));
于 2011-05-12T08:21:37.553 回答
0

在高低搜索之后,我得出的结论是,无法在编译的查询中使用可重用的表达式,更不用说需要参数的表达式了。

以下代码的意图不可能以任何形式或方式实现。

static Expression<Func<Prescription, bool>> filter1 = x => (FilterHpID == null || x.Prescriber.HPID == 1);

compiledQuery = System.Data.Objects.CompiledQuery.Compile((MyEntities entities, int id) =>
                    (from pre in entities.Prescription
                     where pre.PatientID == id
                     select pre)
                     .Where(filter1));

我们将开始研究使用数据库视图来解决首先使用编译查询的需要。如果不必编译 L2E 查询以避免花费近 2 秒的延迟,则可以添加可重用的表达式过滤器。

于 2011-05-13T03:45:55.463 回答