2012-02-14 4 views
1

Я играю с отображением запросов Linq на своих бизнес-объектах в моей базе данных Entity Framework. Кто-нибудь еще спустился по этому пути - или более того, есть ли лучший способ сделать это.Отображение выражений в Linq

То, что я хочу сделать это, чтобы иметь возможность запускать простые запросы к моей бизнес-слой из моего слоя пользовательского интерфейса без добавления дополнительных методов к менеджеру (BL Layer) или Repository (DA Layer)

я получил, что я могу описать проекцию, которую я хочу в слое пользовательского интерфейса, и не нужно создавать отдельный класс или специальный метод в моем менеджере или выполнять дополнительное кодирование на моем уровне DA для эффективного выполнения запроса (в этом случае ключ + агрегированные данные)

var promoSource = new Queryable<BL.Promo>(new PromoQueryProvider());//When executed, Maps a BL Promo code query to an EF.PromoCode query 
var query = from x in promoSource 
    where x.PromoCode != null && x.OrderDate >= startDate && x.OrderDate <= endDate 
    group x by x.PromoCode 
    into result 
    select new 
    { 
    PromoCode = result.Key.Trim(), 
    AverageOrderValue = result.Average(x => x.OrderSubtotal), 
    NumberOfOrders = result.Count() 
    }; 
var results = query.ToList(); //Executes the query in the data layer and passes back the projected data 
promosDataView.DataSource = results; 
promosDataView.DataBind(); 

где раньше мне нужно было бы добавить класс для представления вида OBJE ct, метод в Менеджере, чтобы либо построить сводные данные от объектов, , либо переадресовать вызов на уровень данных для извлечения данных из базы данных.

Кажется, что все работает нормально, в ограниченном числе случаев, но я также чувствую, что я пропускаю лодку с точки зрения правильного разделения. Я собираюсь перехитрить в том, чтобы разделить слои для простых сценариев отчетности в приложении для электронной торговли? Разве я не получаю такую ​​же выгоду, если бы я просто использовал EF Datasource на странице aspx?

+1

Проголосовало, чтобы перенести это на StackOverflow. –

+0

Что делает PromoQueryProvider? – kerem

ответ

0

Я начал спускаться по этой дороге с некоторым начальным успехом. Для меня ключ преобразовывал части выражений, которые ссылались на A.MemberOfA на выражения, ссылающиеся на B.MemberOfB. Например, у вас есть бизнес-объект A:

class A { public bool Selected { get; set; } } 

и объект данных (сущность) B:

class B { public int SelectedInd { get; set; } } 

Как вы можете видеть, в базе данных, выбранное состояние B определяются по индикатору int. Если вы хотите, чтобы получить все выбранные A с, вы можете иметь предикат:

Expression<Func<A, bool>> aPredicate = a => a.Selected; 

Теперь вам нужно выполнить этот предикат на вашем наборе сущностей. Может быть, ваш бизнес-правило это B выбирается, если SelectedInd > 0:

Expression<Func<B, bool>> bPredicate = b => b.SelectedInd > 0; 

Для меня, трюк был ExpressionVisitor класс. Расширяя этот класс и переопределить метод Visit, вы можете заменить детали, которые ссылаются на A и A.Selected со ссылками на B и B.SelectedInd > 0:

class ExpressionTranslator : ExpressionVisitor 
{ 
    public Expression<Func<B, bool>> TranslatePredicate(Expression<Func<A, bool>> predicate) 
    { 
     return (Expression<Func<B, bool>>)this.Visit(predicate); 
    } 

    public override Expression Visit(Expression exp) 
    { 
     if (exp is Expression<Func<A, bool>>) 
     { 
      Expression<Func<A, bool>> predicate = (Expression<Func<A, bool>>)exp; 
      Expression body = this.Visit(predicate.Body); 
      ParameterExpression parameter = (ParameterExpression)this.Visit(predicate.Parameters[0]); 
      return Expression.Lambda<Func<B, bool>>(body, parameter); 
     } 
     else if (exp is ParameterExpression) 
     { 
      ParameterExpression param = (ParameterExpression)exp; 
      if (param.Type == typeof(A)) 
       return bPredicate.Parameters[0]; 
     } 
     else if (exp is MemberExpression) 
     { 
      MemberExpression mbrExpr = (MemberExpression)exp; 
      if (mbrExpr.Member == typeof(A).GetProperty("Selected")) 
       return this.Visit(bPredicate.Body); 
     } 
     else 
      return base.Visit(exp); 
    } 
} 

Конечно, вы можете себе представить, что делает эту логику более общий характер. В моей собственной реализации я регистрирую селектора отображения объектов, так что ExpressionTranslator.Visit динамически выбирает выражения для возврата на основе exp.

Надеюсь, это поможет.

Смежные вопросы