【问题标题】:Is there a way to use C# 9.0 conditional expressions in a C# 7.3 project?有没有办法在 C# 7.3 项目中使用 C# 9.0 条件表达式?
【发布时间】:2021-08-17 20:38:02
【问题描述】:

找到了一种对抽象类的继承类使用投影的好方法 How to avoid repeating property projections when using EF Core inheritance?

var r1 = dbContext.Lessons.Select<Lesson, LessonDto>(l =>
    l is ArticleLesson
        ? new ArticleLessonDto
        {
            Id = l.Id, // This is repeated below
            Title = l.Title, // This is repeated below
            // ...other properties that I would have to repeat below
            Content = (l as ArticleLesson).Content,
        }
        : l is VideoLesson
            ? new VideoLessonDto
            {
                Id = l.Id, // This is repeated above
                Title = l.Title, // This is repeated above
                // ...other properties that I would have to repeat above
                VideoUrl = (l as VideoLesson).VideoUrl,
            }
            : null
)

问题是它只在需要 dotnet 5 的 C# 9.0 中工作。
我正在从事的项目在 dotnet 4.7 和 C# 7.3 上运行,我不决定改变它。
与上面链接代码的主要区别是我需要一个 IQueryable 这意味着我不能使用 .ToList() 或任何可以实现查询的东西。

我尝试将条件提取为表达式和扩展方法,但 EF 尝试将其转换为 SQL,这当然会失败。

public static Expression<Func<Lesson, LessonDto>> CreateLessonDto = l => l.CreateLessonDto();

public static LessonDto CreateLessonDto(this Lesson Lesson)
{
    if (Lesson is ArticleLesson)
        return new ArticleLessonDto();
    else if (Lesson is VideoLesson)
        return new VideoLessonDto();

    return null;
}

var r1 = dbContext.Lessons.Select(CreateLessonDto);

使用 .OfType 和 Union 似乎也不起作用。

任何解决此问题的想法都将受到高度赞赏。

【问题讨论】:

  • 在第一个示例中,我没有看到 C# 9 特定的语法。也许问题是 EF 6 与 EF Core 5。你能确认你使用的 Entity Framework 的版本吗?
  • @vernou 标记并使用 EF6。这 ? :在选择中是 C# 9,因为条件返回不同的类型 web.archive.org/web/20210807210937/https://docs.microsoft.com/…
  • 等等..你认为嵌套三元结构很好吗?

标签: c# entity-framework linq entity-framework-6


【解决方案1】:

我建议将LINQKit 用于此类任务。它将简化构建此类扩展。

您必须指示 LINQKit 如何将您的投影注入到表达式树中。

[Expandable(nameof(CreateLessonDtoImpl))]
public static LessonDto CreateLessonDto(this Lesson Lesson) 
   => throw new NotImplementedException();

private static Expression<Func<Lesson, LessonDto>> CreateLessonDtoImpl()
{
    return l => l is ArticleLesson
        ? ((ArticleLesson)l).CreateArticleLessonDto()
        : l is VideoLesson
            ((VideoLesson)l).CreateVideoLessonDto()
            : null;
}

// helpers

[Expandable(nameof(CreateArticleLessonDtoImpl))]
public static ArticleLessonDto CreateArticleLessonDto(this ArticleLesson Lesson) 
   => throw new NotImplementedException();

private static Expression<Func<ArticleLesson, ArticleLessonDto>> CreateArticleLessonDtoImpl()
{
    return l => new ArticleLessonDto
    {
        Id = l.Id, // This is repeated below
        Title = l.Title, // This is repeated below
        // ...other properties that I would have to repeat below
        Content = l.Content,
    };
}

[Expandable(nameof(CreateVideoLessonDtoImpl))]
public static VideoLessonDto CreateVideoLessonDto(this VideoLesson Lesson) 
   => throw new NotImplementedException();

private static Expression<Func<VideoLesson, VideoLessonDto>> CreateVideoLessonDtoImpl()
{
    return l => new VideoLessonDto
    {
        Id = l.Id, // This is repeated below
        Title = l.Title, // This is repeated below
        // ...other properties that I would have to repeat below
        VideoUrl = l.VideoUrl,
    };
}

查询中的用法:

var r1 = dbContext.Lessons
   .AsExpandable() // important
   .Select(l => l.CreateLessonDto());

这种方法有几个好处:

  • 您可以在其他查​​询中重复使用这些方法
  • 生成有效的 SQL
  • 不仅可以用于投影

对于 EF Core,LINQKit 已简化其用法,不再需要在查询中使用 AsExpandable() 调用。你可以在构建DbContextOptions时指定WithExpressionExpanding

builder
    .UseSqlServer(connectionString)
    .WithExpressionExpanding(); // enabling LINQKit extension

【讨论】:

  • 看起来不错。不幸的是,我现在无法测试它,因为我正在处理一个不同的问题。将尽快尝试。第一个私有静态应该是 CreateLessonDtoImpl 吧?
  • 是的,会更正。凭记忆写;)
猜你喜欢
  • 2022-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-05
  • 1970-01-01
  • 2010-12-17
  • 2023-04-09
  • 1970-01-01
相关资源
最近更新 更多