2

我有这样的事情:

public class HomeWork
{
    public DateTime Starts {get;set;}
    public DateTime Ends {get;set;}
}

我想做一个这样的 LINQ 查询:

var xxx = from hwrk in HomeWorks
    where hwrk.Starts.Between(date1, date2) || hwrk.Ends.Between(date1, date2) || 
        date1.Beetween(hwrk.Starts, hwrk.Ends) || date2.Between(hwrk.Starts, hwrk.Ends)
    select hwrk;

我可以制作一个适用于 DateTime 的扩展,但我需要该扩展也适用于 LINQ to SQL。

我发现了一些在内部使用 Where 方法的示例,但它适用于 IQueryable 接口。但我需要它适用于单个属性。在某些示例中,他们使用表达式,但我找不到执行此类操作的示例。

您能否举一个适用于属性和常规变量并且也适用于 LINQ to SQL 的扩展示例?或者只是这是我不能做的事情?

4

3 回答 3

2

您可以实现一个返回“介于”表达式的函数,然后使用LinqKit 的 AsExpandable,它允许您将可重用的表达式插入到您的 lambda 表达式中。

不过这会很复杂,我不建议在这种特殊情况下这样做。我认为手动执行会更简单,会重复,但会更简单,更容易维护。

话虽如此,我已经在下面使用表达式实现了它,因此您可以看到该方法。

第一步是创建一个返回“介于”表达式的方法。我已经使用IComparable接口实现了这一点,因此您可以将其用于任何可比较的类型。

public static Expression<Func<TComparable, TComparable, TComparable, bool>> Between<TComparable>(this TComparable thisComparable) where TComparable : IComparable
{
    return (value, lower, upper) => lower.CompareTo(value) <= 0 && value.CompareTo(upper) <= 0;
}

然后你可以像这样使用它:

var between = Extensions.Between<DateTime>();

AsExpandable可以使用 LinqKit 的和Invoke方法将该表达式插入到您的查询中:

var query = from m in context.Members.AsExpandable()
            where between.Invoke(m.CreatedDate, startDate, endDate)
            select m;

这在使用 Linq to SQL 时会产生以下 SQL:

-- Region Parameters
DECLARE @p0 DateTime = '2012-09-13 11:01:10.103'
DECLARE @p1 DateTime = '2012-09-20 11:01:10.103'
-- EndRegion
SELECT [t0].[MemberID], [t0].[Firstname], [t0].[Surname], [t0].[Email], [t0].[CreatedDate]
FROM [Member] AS [t0]
WHERE (@p0 <= [t0].[CreatedDate]) AND ([t0].[CreatedDate] <= @p1)
于 2012-09-20T10:14:54.287 回答
0

你发现使用IQueryable接口是要走的路,你不能那样做你想做的事,你必须接受你的表达并对待它,以便 Linq to SQL 提供程序可以理解它,我知道的唯一方法是:

  • 将您的方法的“虚拟”实现编写Between为的扩展方法DateTime
  • 编写一个您将调用的IQueryable<T>扩展方法(例如),而不是,将相同的谓词传递给它ExpandWhere
  • 在里面Expand你必须分析你收到的表达式树并生成一个新的,你的Between调用被翻译成and表达式<==>检查,Linq to SQL 会理解

如果您的问题只是这种特定情况,我会按照 Jon48 所说的做 :)

于 2012-09-20T10:14:41.543 回答
0

我可能不会直接回答您关于扩展 Linq2SQL 的一般性问题,但从您的示例中,您正在寻找在某个时间段内开始或结束的作业。在逻辑方面,鉴于start < end,您可以简化这样做:

where hwrk.Starts <= date2 && hwrk.Ends >= date1
于 2012-09-20T09:57:49.870 回答