【问题标题】:How to use expression to assign property in LINQ Select new如何使用表达式在 LINQ Select new 中分配属性
【发布时间】:2019-01-17 23:51:02
【问题描述】:

我在泛型类中有以下情况:

IQueryable<TQuote> query = GetQuotes(ctx)

其中ctx 是数据库上下文,GetQuotes 返回DbSet&lt;TQuote&gt;

然后在代码的某个地方执行查询。其简化形式如下:

var list = await query
    .Select(v => new
    {
        v.Id,
        TimeZone = v.Property != null ? (int?)v.Property.TimeZone : null
        // and about 10 more simple properties like v.Id above
    }
    .ToListAsync();

其中Property 是导航属性(到另一个表),TimeZone 只是 C# 中int? 类型的常规数据库列/属性。

在我尝试将通用类与没有导航属性 Property 的实体一起使用之前,一切正常。所以,我想用类的抽象成员替换“硬编码”表达式v.Property != null ? (int?)v.Property.TimeZone : null,然后为不同的TQuote 类型覆盖它。

我在这个签名上尝试了一些东西:

protected abstract Expression<Func<TQuote, int?>> GetTimeZone();

但是如果我在 LINQ 中使用它(直接或先分配给某个变量),那么 TimeZone 的签名也会更改为 Expression&lt;...&gt;,如果我尝试使用 ...Compile().Invoke(v),那么 LINQ 会抱怨 LINQ 到实体不支持。

我看到了这个答案:Create a Dynamic Linq to EF Expression to Select IQueryable into new class and assign properties 但是,它手动构建了整个选择器,并且考虑到我总共有 16 个属性,创建和维护起来会很痛苦。所以,我想知道我是否可以只对这个TimeZone 做点什么,而将其余的留在上面的简单 LINQ 表单中。

有没有可能,如果有,具体怎么做?

【问题讨论】:

    标签: c# entity-framework linq expression


    【解决方案1】:

    试试 nuget LINQKit,https://github.com/scottksmith95/LINQKit

    以下是我的尝试。 LinqKit 提供了AsExpandable()Invoke(v) 方法。 我编写了Area.TimeZoneRegion.RegionalTimeZone 之类的属性。

    using LinqKit;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    
    class QuoteResult
    {
        public int Id { get; set; }
        public int? TimeZone { get; set; }
        public string Note { get; set; }
    }
    
    abstract class QuoteHelper<TQuote> where TQuote : Quote
    {
        protected abstract Expression<Func<TQuote, int?>> GetTimeZone { get; }
    
        public IEnumerable<QuoteResult> GetQuoteResults(
            EfExpressionPropertyDbContext ctx)
        {
            IQueryable<TQuote> query = GetQuotes(ctx);
            var getTimeZone = GetTimeZone;
    
            var list = query
                .AsExpandable()
                .Select(v => new QuoteResult
                {
                    Id = v.Id,
                    TimeZone = getTimeZone.Invoke(v),
                    Note = v.Note
                    // and about 10 more simple properties like v.Id above
                })
                .ToList();
            return list;
        }
    
        public IQueryable<TQuote> GetQuotes(
            EfExpressionPropertyDbContext ctx)
        {
            return ctx.Set<TQuote>();
        }
    }
    
    class CommonQuoteHelper : QuoteHelper<CommonQuote>
    {
        protected override Expression<Func<CommonQuote, int?>> GetTimeZone
        {
            get { return q => q.Area != null ? (int?)q.Area.TimeZone : null; }
        }
    }
    
    class PeculiarQuoteHelper : QuoteHelper<PeculiarQuote>
    {
        protected override Expression<Func<PeculiarQuote, int?>> GetTimeZone
        {
            get { return q => q.Region != null ? (int?)q.Region.RegionalTimeZone : null; }
        }
    }
    

    【讨论】:

    • 酷,谢谢!这正是我一直在寻找但找不到的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2023-03-04
    相关资源
    最近更新 更多