我怎样才能避免在Linq To Entities中重复自己?

时间:2009-06-13 20:57:54

标签: linq-to-entities

在查询时,我发现自己在LinqToEntities中过多地重复业务规则。这不好。 ;)

说我有两张桌子:

会员

  • Id
  • 名称

成员

  • Id
  • MemberId(fk to member.Id)
  • StartDate
  • ExpirationDate
  • IsCancelled

现在我将有效会员资格定义为:

  1. 现在介于StartDate和ExpirationDate之间
  2. IsCancelled为false
  3. 所以现在我会在库中编写函数,比如......:

    1. GetActiveMemberships
    2. GetMembersWithActiveMemberships
    3. MemberHasActiveMembership
    4. (等)
    5. ...所以在使用LinqToEntities的所有这些函数中,我的代码都是......:

      ...
      And membership.IsCancelled = 0 _
      And membership.StartDate < Now() _
      And membership.ExpirationDate > Now() _
      ...
      

      避免在每个Linq-to-entities查询中重复此操作的最佳方法是什么? 我可以将我对有效会员资格的定义分开并将其应用于其他功能吗?

1 个答案:

答案 0 :(得分:0)

看起来你正在使用VB.NET。我为回答一些C#代码而道歉,但希望你能翻译。

我可以想到几种方法来解决这个问题。第一个想法是创建一个返回类型为Func的谓词的函数。这允许EF将谓词反向工程为查询。例如:

static Func<MemberShip, bool> IsActiveMember()
{
    return m => (
        (m.IsCancelled == 0) &&
        (m.StartDate < DateTime.Now) &&
        (m.ExpirationDate > DateTime.Now));
}

这种方法的一大缺点是你不能使用“理解查询”语法(来自...... where ... select)。您必须直接使用LINQ方法,如:

var context = new AppEntities();
var activeMembers = context.MemberShipSet.Where(IsActiveMember());

根据您需要使用它的方式,更好的方法可能是创建一个函数或属性,该函数或属性返回预过滤的MemberShip实体集,仅包含“活动”实体。以下是使用以下属性扩展EF设计器创建的上下文类的示例:

partial class AppEntities
{
    public IQueryable<MemberShip> ActiveMembers
    {
        get
        {
            return
                from m in this.MemberShipSet
                where (
                    (m.IsCancelled == 0) &&
                    (m.StartDate < DateTime.Now) &&
                    (m.ExpirationDate > DateTime.Now))
                select m;
        }
    }
}

这种方法的巧妙之处在于您可以针对ActiveMembers制定LINQ查询。例如:

var lastThirty = DateTime.Now.AddDays(-30);
var context = new AppEntities();
var recentActiveMembers =
    from mr in context.ActiveMembers
    where (mr.StartDate > lastThirty)
    select mr;