【问题标题】:Dynamically selecting fields in a linq query在 linq 查询中动态选择字段
【发布时间】:2016-01-12 20:03:37
【问题描述】:

我有一个 linq 查询,我希望只动态选择用户请求的字段。

目前我正在将我的作业映射到这样的数据转换对象:

var jobs = (from p in jobsDB
select new JobReportDTO()
{
    JobID = p.JobID,
    EventType = p.EventType,
    DateApproved = p.ApprovedDate,
    DateEntered = p.EnteredDate,
    DateClosed = p.ClosedDate,
    StartDate = p.StartDate,
    FinishDate = p.FinishDate,
    InsuredName = p.InsuredName,
    StreetAddress = p.StreetAddress,
    Suburb = p.Suburb,
    State = p.State,
    Postcode = p.Postcode,
    .... etc

在这个函数中,我有许多布尔变量,用于标识是否应该将该字段发送到视图,即:

public bool ShowInsuredName { get; set; }
public bool ShowSuburb { get; set; }
public bool ShowICLA { get; set; }
public bool ShowClaimNumber { get; set; }
public bool ShowFileMananger { get; set; }
public bool ShowSupervisor { get; set; }
public bool ShowStatus { get; set; }
... etc

如何修改我的 linq 查询以仅显示选定的字段?

我试过了

var jobs = (from p in jobsDB
    select new JobReportDTO()
    {
        JobID = p.JobID,
        jobReport.ShowEventType == true ? EventType = p.EventType : "",
        ... etc

但我得到“无效的初始化程序成员声明器”

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    如果您负担得起 LINQ 方法语法并为 public bool Show{DTOPropertyName} { get; set; } 之类的选项使用强大的命名约定,那么您可以借助 System.Linq.Expressions 和以下小助手方法让您的生活更轻松

    public static class MyExtensions
    {
        public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, object options)
        {
            var memberInit = (MemberInitExpression)selector.Body;
            var bindings = new List<MemberBinding>();
            foreach (var binding in memberInit.Bindings)
            {
                var option = options.GetType().GetProperty("Show" + binding.Member.Name);
                if (option == null || (bool)option.GetValue(options)) bindings.Add(binding);
            }
            var newSelector = Expression.Lambda<Func<TSource, TResult>>(
                Expression.MemberInit(memberInit.NewExpression, bindings), selector.Parameters);
            return source.Select(newSelector);
        }
    }
    

    它的作用是删除与ShowProperty 关联的赋值为false

    用法很简单

    var jobs = jobsDB.Select(p => new JobReportDTO
    {
        JobID = p.JobID,
        EventType = p.EventType,
        DateApproved = p.ApprovedDate,
        DateEntered = p.EnteredDate,
        DateClosed = p.ClosedDate,
        StartDate = p.StartDate,
        FinishDate = p.FinishDate,
        InsuredName = p.InsuredName,
        StreetAddress = p.StreetAddress,
        Suburb = p.Suburb,
        State = p.State,
        Postcode = p.Postcode,
        .... etc 
    }, jobReport);
    

    如果您在调试器中设置断点并检查 newSelector 变量,您将看到仅包含不具有 ShowProperty(如 JobID)或具有 ShowProperty = true 的属性。

    【讨论】:

    • 这只会从数据库中获取所需的记录,对吧?
    • 它只是一个Select 部分并控制获取的字段(列)。记录呢,如果有的话,它会获取您在Where 子句中指定的内容。
    • 是的,对不起,我的意思是列 :)
    • 没问题,那么是的:)
    • 假设使用EF,可以加var sql = jobs.ToString();查看实际SQL查询。
    【解决方案2】:

    试试这个方法:

    EventType = jobReport.ShowEventType == true ? p.EventType : string.Empty,
    

    【讨论】:

    • 据我了解,当相应的 bool 为 false 时,他不希望 EventType 成为他的对象的一部分
    • @AlexanderDerck JobReportDTO 已经是一个属性/字段。他可以将其设置为 null 否则
    • 我知道,但是“如何修改我的 linq 查询以仅显示选定的字段?”只是听起来他想要一个只有某些属性的对象。
    • 这很完美,谢谢,我可以使用空对象(而不是完全丢失的属性)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 2013-07-02
    • 1970-01-01
    相关资源
    最近更新 更多