我可以重用IQueryable <dynamic> .Select()语句吗?

时间:2018-06-13 18:54:39

标签: c# entity-framework

我正在使用C#和Entity Framework v6.2.0

在存储库类中,我有这个功能:

public IQueryable<dynamic> GetRelatedCallDetailsAsNoTracking(Guid callThreadId)
    {
        return _context.CallDetails
            .AsNoTracking()
            .Include(callDetail => callDetail.Callers)
            .Select(callDetail => new
            {
                callDetail.Id,
                callDetail.EnteredByEmail,
                callDetail.CallStartTime,
                callDetail.CallDirectionIsIncoming,
                callDetail.CallThread_Id,
                Children = callDetail.Children.Select(child => new
                {
                    child.FirstName,
                    child.LastName,
                    child.DateOfBirth
                }),
                Callers = callDetail.Callers.Select(y => new
                {
                    y.FirstName,
                    y.LastName,
                    y.PhoneNumber.Number
                }),
                callDetail.SensitiveCall,
                callDetail.SuccessStory
            })
            .Where(x => x.CallThread_Id == callThreadId)
            .OrderByDescending(x => x.CallStartTime);
    }

在同一个Repo中,我有第二个函数,它具有完全相同的查询和一些添加的.Where(...)语句。

是否可以执行以下操作:

public IQueryable<dynamic> SecondQuery(Guid callThreadId)
{
    return BaseQuery()
        .Where(x => x.CallTherad_Id == callThreadId)
        .OrderByDescending(x => x...);
}
public IQueryable<dynamic> SecondQuery(Guid callThreadId, string secondParameter, bool thirdParameter)
{
    return BaseQuery()
        .Where(x => x...)
        .Where(x => x...)
        .Where(x => x...)
        .OrderByDescending(x => x...);
}

我试过了:

private IQueryable<dynamic> BaseQuery()
{
    return _context.CallDetails
        .AsNoTracking()
        .Include(callDetail => callDetail.Callers)
        .Select(callDetail => new
        {
            callDetail.Id,
            callDetail.EnteredByEmail,
            callDetail.CallStartTime,
            callDetail.CallDirectionIsIncoming,
            callDetail.CallThread_Id,
            Children = callDetail.Children.Select(child => new
            {
                child.FirstName,
                child.LastName,
                child.DateOfBirth
            }),
            Callers = callDetail.Callers.Select(y => new
            {
                y.FirstName,
                y.LastName,
                y.PhoneNumber.Number
            }),
            callDetail.SensitiveCall,
            callDetail.SuccessStory
        });
}

public IQueryable<dynamic> GetRelatedCallDetailsAsNoTracking(Guid callThreadId)
{
    return BaseQuery().Where(x => x.CallThread_Id == callThreadId);
}

但是这给我带来了错误:

  

表达式树可能不包含动态操作

1 个答案:

答案 0 :(得分:0)

您可以重复使用查询的任何部分。作为问题的解决方案,您需要定义一个可以在方法签名中使用的非匿名类型:

class CallDetails {
    public int Id { get; set; }
    //...
    IQueryable<CallDetailsChild> Children { get; set; }
    IQueryable<CallDetailsCaller> Callers { get; set; }
    //...
}

class CallDetailsChild {
    //...
}

class CallDetailsCaller {
    //...
}

//...

private IQueryable<CallDetails> BaseQuery()
{
    return _context.CallDetails
        .AsNoTracking()
        .Include(callDetail => callDetail.Callers)
        .Select(callDetail => new CallDetails
        {
            callDetail.Id,
            callDetail.EnteredByEmail,
            callDetail.CallStartTime,
            callDetail.CallDirectionIsIncoming,
            callDetail.CallThread_Id,
            Children = callDetail.Children.Select(child => new CallDetailsChild
            {
                child.FirstName,
                child.LastName,
                child.DateOfBirth
            }),
            Callers = callDetail.Callers.Select(y => new CallDetailsCaller
            {
                y.FirstName,
                y.LastName,
                y.PhoneNumber.Number
            }),
            callDetail.SensitiveCall,
            callDetail.SuccessStory
        });
}

这个解决方案有点冗长,但如果你想使用自定义类型而不是实体类型并且像这样重用它,那么这是你唯一的选择。