2016-08-15 1 views
0

마지막 선택시 어떻게 투영 할 수 있습니까? 문자열 prop.Name으로 정의 된 속성을 SeriesProjection 개체로 선택해야합니다. GroupBy를 들어LINQ to SQL 투영시 문자열을 기준으로 속성 이름 선택

public override IQueryable<SeriesProjection> FilterOn(string column) 
{ 
    //Get metadata class property by defined Attributes and parameter column 
    var prop = typeof(CommunicationMetaData) 
       .GetProperties() 
       .Single(p => p.GetCustomAttribute<FilterableAttribute>().ReferenceProperty == column); 

    var attr = ((FilterableAttribute)prop.GetCustomAttribute(typeof(FilterableAttribute))); 

    var param = Expression.Parameter(typeof(Communication)); 

    Expression conversion = Expression.Convert(Expression.Property(param, attr.ReferenceProperty), typeof(int)); 

    var condition = Expression.Lambda<Func<Communication, int>>(conversion, param); // for LINQ to SQl/Entities skip Compile() call 

    var result = DbQuery.Include(prop.Name) 
      //.GroupBy(c => c.GetType().GetProperty(attr.ReferenceProperty)) 
      .GroupBy(condition) 
      .OrderByDescending(g => g.Count()) 
      .Select(group => new SeriesProjection() 
      { 
       Count = group.Count(), 
       Id = group.Key, 
       //set this navigation property dynamically 
       Name = group.FirstOrDefault().GetType().GetProperty(prop.Name) 
      }); 

    return result; 
} 

나는 항상 Communication 기업에 INT 년대 FK 속성 이름을 사용하지만, 선택을 위해 나는 표현을 알아낼 수 없습니다.

[편집] 일부 표현 도우미 라이브러리없이

System.Data.Entity.Infrastructure.DbQuery<Communication> DbQuery; 
--- 
[MetadataType(typeof(CommunicationMetaData))] 
public partial class Communication 
{ 
    public int CommunicationId { get; set; } 
    public Nullable<int> TopicId { get; set; } 
    public int CreateById { get; set; } 
    public virtual Employee CreateByEmployee { get; set; } 
    public virtual Topic Topic { get; set; } 
} 
--- 
public class CommunicationMetaData 
{ 
    [Filterable("By Employee", nameof(Communication.CreateById))] 
    public Employee CreateByEmployee { get; set; } 
    [Filterable("By Topic", nameof(Communication.TopicId))] 
    public Topic Topic { get; set; } 
} 
--- 
[AttributeUsage(AttributeTargets.Property)] 
public class FilterableAttribute : System.Attribute 
{ 

    public FilterableAttribute(string friendlyName, string referenceProperty) 
    { 
     FriendlyName = friendlyName; 
     ReferenceProperty = referenceProperty; 
    } 

    public string FriendlyName { get; set; } 

    public string ReferenceProperty { get; set; } 
} 
--- 
public class SeriesProjection 
{ 
    public int Count { get; set; } 
    public int Id { get; set; } 
    public object Name { get; set; } 
} 
+0

더 많은 경험을 위해 아마도 필요하지는 않지만'SeriesProjection','CommunicationMetaData','FilterableAttribute','Communication' 및'DbQuery' 클래스를'column' 입력과 함께 게시하여 테스트 할 수 있습니까? – uTeisT

+0

'GroupBy' 표현식을 생성했는데, 왜 그만합니까? –

+0

@JeffMercado 그것은 정확하게 이해할 수없는 나의 투쟁입니다. –

답변

1

, 당신은 수동으로 전체 선택 식을 구축해야합니다.

선택기의 입력은 입력 IGrouping<int, Communication> 결과 유형의 매개 변수가 될 것이다 - SeriesProjection, 상기 본체 MemberInit 표현 될 것이다

var projectionParameter = Expression.Parameter(typeof(IGrouping<int, Communication>), "group"); 
var projectionType = typeof(SeriesProjection); 
var projectionBody = Expression.MemberInit(
    // new SeriesProjection 
    Expression.New(projectionType), 
    // { 
    //  Count = group.Count(), 
    Expression.Bind(
     projectionType.GetProperty(nameof(SeriesProjection.Count)), 
     Expression.Call(typeof(Enumerable), "Count", new[] { typeof(Communication) }, projectionParameter)), 
    //  Id = group.Key 
    Expression.Bind(
     projectionType.GetProperty(nameof(SeriesProjection.Id)), 
     Expression.Property(projectionParameter, "Key")), 
    //  Name = group.FirstOrDefault().Property 
    Expression.Bind(
     projectionType.GetProperty(nameof(SeriesProjection.Name)), 
     Expression.Property(
      Expression.Call(typeof(Enumerable), "FirstOrDefault", new[] { typeof(Communication) }, projectionParameter), 
      prop.Name)) 
    // } 
    ); 
var projectionSelector = Expression.Lambda<Func<IGrouping<int, Communication>, SeriesProjection>>(projectionBody, projectionParameter); 

후 물론 단순히 사용

var result = DbQuery.Include(prop.Name) 
     .GroupBy(condition) 
     .OrderByDescending(g => g.Count()) 
     .Select(projectionSelector);