Как я могу избежать повторения в LinqToEntities? - PullRequest
0 голосов
/ 14 июня 2009

Я часто повторяю бизнес-правила в своих LinqToEntities при запросах. Это не хорошо. ;)

Скажем, у меня есть две таблицы:

Участник

  • Id
  • Имя

ЧЛЕНСТВО

  • Id
  • MemberId (fk to member.Id)
  • StartDate
  • Дата истечения срока действия
  • IsCancelled

Теперь я определяю действительное членство как:

  1. Сейчас между StartDate и ExpirationDate
  2. IsCancelled является ложным

Так что теперь я буду писать функции в репозиториях, как ...:

  1. GetActiveMemberships
  2. GetMembersWithActiveMemberships
  3. MemberHasActiveMembership
  4. (и т.д.) * * тысяча сорок-четырь

... Итак, во всех этих функциях, использующих LinqToEntities, у меня есть код, подобный ..:

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

Каков наилучший способ избежать повторения этого в каждом отдельном запросе Linq-to-entity?
Могу ли я отделить свое определение действительного членства и применить его в других функциях?

1 Ответ

0 голосов
/ 14 июня 2009

Похоже, вы используете VB.NET. Я прошу прощения за ответ с некоторым кодом C #, но, надеюсь, вы сможете перевести.

Я могу придумать пару способов справиться с этим. Первая идея заключается в создании функции, которая возвращает предикат типа Func. Это позволяет EF преобразовать предикат в запрос. Например:

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

Большим недостатком этого подхода является то, что вы не можете использовать синтаксис «запрос на понимание» (откуда ... выберите ...). Вы должны использовать методы 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;
        }
    }
}

Отличительной особенностью этого подхода является то, что вы можете формулировать запросы LINQ к ActiveMembers. Например:

var lastThirty = DateTime.Now.AddDays(-30);
var context = new AppEntities();
var recentActiveMembers =
    from mr in context.ActiveMembers
    where (mr.StartDate > lastThirty)
    select mr; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...