简体   繁体   English

在实体框架查询中使用子属性的方法

[英]Use method for child property in entity framework query

I was able to use a method for entity framework from the post below. 我能够从下面的帖子中使用实体框架的方法。

Use method in entity framework query 在实体框架查询中使用方法

But how can I use an expression for an inner property? 但是如何使用表达式作为内部属性? The code below tries to grab a list of gyms, but I want to filter those gyms by the same expression as I did with the event directory. 下面的代码试图获取健身房列表,但我想通过与事件目录相同的表达式过滤这些健身房。 This time I want it applied to the child property Event of EventGym. 这次我希望它应用于EventGym的子属性Event。 The EventGym.Event property that is. EventGym.Event属性是。

EventGym.cs EventGym.cs

[Table("EventGym", Schema = "GrassrootsHoops")]
public class EventGym : BaseEntity
{
    public int EventId { get; set; }

    [ForeignKey("EventId")]
    public virtual Event Event { get; set; }
}

Get Gyms 得到健身房

public List<MobileVenueModel> GetGyms(string applicationId)
{
    return (from e in _eventsRepository.DataContext.EventGyms
            //where GetEvent(applicationId)
            select new MobileVenueModel
                {
                    Id = e.Id
                }).ToList();
}

public Expression<Func<Event, bool>> GetEvent(string applicationId)
{
    return q => q.Active && q.Visible && q.MobileEventApplications.Any(m =>
                          m.MobileApplication.ApplicationId == applicationId &&
                          (!m.MobileApplication.ActivationLength.HasValue || DbFunctions.AddDays(DateTime.Now, 1) < DbFunctions.AddMonths(m.MobileApplication.DateActivated, m.MobileApplication.ActivationLength.Value)));
}

Build all of the expressions dynamically: 动态构建所有表达式:

public static Expression<Func<Event,bool>> GetEvent( string applicationId )
{
    var arg = Expression.Parameter( typeof( Event ), "e" );

    return ( Expression<Func<Event, bool>> )Expression.Lambda( GetEvent( arg, applicationId ), arg );
}

public static Expression<Func<EventGym, bool>> GetEventGymPredicateExpression( string applicationId )
{
    var arg = Expression.Parameter( typeof( EventGym ), "eg" );

    var propSelector = Expression.Property( arg, "Event" );

    var existingExp = GetEvent( propSelector, applicationId );

    return ( Expression<Func<EventGym, bool>> )Expression.Lambda( existingExp, arg );
}

public static Expression GetEvent( Expression arg, string applicationId )
{
    // q.Active
    var activeProp = Expression.Property( arg, "Active" );

    // q.Visible
    var visibleProp = Expression.Property( arg, "Visible" );

    // q.Active && q.Visible
    var and0 = Expression.AndAlso( activeProp, visibleProp );

    var meaProp = arg.Type.GetProperty( "MobileEventApplications" );
    var colType = meaProp.PropertyType;
    var entityType = colType.GetGenericArguments().Single();

    var mArg = Expression.Parameter( entityType, "m" );

    // m.MobileApplication
    var maProp = Expression.Property( mArg, "MobileApplication" );
    // m.MobileApplication.ApplicationId
    var appIdProp = Expression.Property( maProp, "ApplicationId" );
    // m.MobileApplication.ApplicationId == applicationId
    var appIdEqual = Expression.Equal( appIdProp, Expression.Constant( applicationId ) );

    // m.MobileApplication.ActivationLength
    var alProp = Expression.Property( maProp, "ActivationLength" );
    // m.MobileApplication.ActivationLength.HasValue
    var hvProp = Expression.Property( alProp, "HasValue" );
    // !m.MobileApplication.ActivationLength.HasValue
    var notHasValue = Expression.Not( hvProp );

    // DbFunctions.AddDays( DateTime.Now, 1 )
    var addDaysFunc = typeof( DbFunctions ).GetMethods().Single( mi => 
        mi.Name == "AddDays" && 
        mi.GetParameters().First().ParameterType == typeof( DateTime? ) );

    var nowPlus1d = Expression.Call( null, addDaysFunc, Expression.Constant( DateTime.Now, typeof( DateTime? ) ), Expression.Constant( 1, typeof( int? ) ) );

    // m.MobileApplication.DateActivated
    var daProp = Expression.Property( maProp, "DateActivated" );
    // m.MobileApplication.ActivationLength.Value
    var alvProp = Expression.Property( alProp, "Value" );
    // DbFunctions.AddMonths( DateActivated, ActivationLength.Value )
    var addMonthsFunc = typeof( DbFunctions ).GetMethods().Single( mi => 
        mi.Name == "AddMonths" &&
        mi.GetParameters().First().ParameterType == typeof( DateTime? ) );

    var addMonths = Expression.Call( null, addMonthsFunc, Expression.Convert( daProp, typeof( DateTime? ) ), Expression.Convert( alvProp, typeof( int? ) ) );

    // AddDays < AddMonths
    var ltOp = Expression.LessThan( nowPlus1d, addMonths );

    // !HasValue || ( AddDays < AddMonths )
    var orOp = Expression.Or( notHasValue, ltOp );

    // AppId == applicationId && ( !HasValue || ( AddDays < AddMonths ) )
    var anyBody = Expression.AndAlso( appIdEqual, orOp );

    var anyPredicate = Expression.Lambda( anyBody, mArg );

    // q.MobileEventApplications
    Expression meaExp = Expression.Property( arg, meaProp );

    var anyMethod = typeof( Queryable ).GetMethods()
        .Single( mi => 
            mi.Name == "Any" && 
            mi.GetParameters().Count() == 2 )
        .MakeGenericMethod( entityType );

    // q.MobileEventApplications.Any( m => anyBody )
    var anyCallExp = Expression.Call( null, anyMethod, Expression.Convert( meaExp, typeof( IQueryable<MobileEventApplication> ) ), anyPredicate );

    return Expression.AndAlso( and0, anyCallExp );

    //return q => q.Active && q.Visible && q.MobileEventApplications.Any(m =>
    //    m.MobileApplication.ApplicationId == applicationId &&
    //    (
    //        !m.MobileApplication.ActivationLength.HasValue || 
    //        DbFunctions.AddDays(DateTime.Now, 1) < DbFunctions.AddMonths(m.MobileApplication.DateActivated, m.MobileApplication.ActivationLength.Value ) ) );

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM