Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 最有效的实体框架代码第一种使用特定子实体展平/投影父实体的方法_Linq_Ef Code First_Entity Framework 5_Code First - Fatal编程技术网

Linq 最有效的实体框架代码第一种使用特定子实体展平/投影父实体的方法

Linq 最有效的实体框架代码第一种使用特定子实体展平/投影父实体的方法,linq,ef-code-first,entity-framework-5,code-first,Linq,Ef Code First,Entity Framework 5,Code First,我有一个具有核心成员的父实体小部件,以及多个具有语言翻译成员的WidgetTranslation子实体,即说明文本,可提供英语、法语、德语等 e、 g 给定languageId我从 DbSet.Select(w => new TranslatedWidget { Id = w.Id, Code = w.Code, LanguageId = w.LanguageId, Name = w.WidgetTranslations.First(wt=>wt.

我有一个具有核心成员的父实体
小部件
,以及多个具有语言翻译成员的
WidgetTranslation
子实体,即
说明
文本,可提供英语、法语、德语等

e、 g

给定
languageId
我从

DbSet.Select(w => new TranslatedWidget
  {
    Id = w.Id,
    Code = w.Code,
    LanguageId = w.LanguageId,
    Name = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Name,
    Description = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Description,
    Summary = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Summary
  });
但我觉得这样做效率很低,而且无法在
widgetranslation
上扩展更多属性


谢谢

我会将
名称
说明
摘要
移动到您的数据的嵌套类中

public class TranslatedWidgetTranslation
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string Summary { get; set; }
}

public class TranslatedWidget
{
    public int Id { get; set; }
    public string Code { get; set; }
    public int LanguageId { get; set; }
    public TranslatedWidgetTranslation Translation { get; set; }
}
然后,您可以投影到该类中,并且只需要一次
第一次
,这将在SQL中只产生一个
TOP(1)
子查询,而不是三个子查询:

DbSet.Select(w => new TranslatedWidget
{
    Id = w.Id,
    Code = w.Code,
    LanguageId = languageId,
    Translation = w.WidgetTranslations
        .Where(wt => wt.LanguageId == languageId)
        .Select(wt => new TranslatedWidgetTranslation
        {
            Name = wt.Name,
            Description = wt.Description,
            Summary = wt.Summary
        })
        .FirstOrDefault()
});
您必须在此处使用
First或default
,LINQ到实体投影中不支持
First

如果不希望使用该嵌套类型,可以先将其投影为匿名类型,然后再转换为最终类,但代码会稍长一些:

DbSet.Select(w => new
{
    Id = w.Id,
    Code = w.Code,
    LanguageId = languageId,
    Translation = w.WidgetTranslations
        .Where(wt => wt.LanguageId == languageId)
        .Select(wt => new
        {
            Name = wt.Name,
            Description = wt.Description,
            Summary = wt.Summary
        })
        .FirstOrDefault()
})
.AsEnumerable()
.Select(x => new TranslatedWidget
{
    Id = x.Id,
    Code = x.Code,
    LanguageId = x.LanguageId,
    Name = x.Translation != null ? x.Translation.Name : null,
    Description = x.Translation != null ? x.Translation.Description : null,
    Summary = x.Translation != null ? x.Translation.Summary : null
});

使用SelectMany通过单个连接展平结构:

var widgetQuery = from w in dbSet.Widgets
                  from wt in w.WidgetTranslations
                  where wt.Language == languageId
                  select new TranslatedWidget
                  {
                     Id = w.Id,
                     Code = w.Code,
                     LanguageId = w.LanguageId,
                     Name = wt.Name,
                     Description = wt.Description,
                     Summary = wt.Summary
                  });

我在这里假设,对于给定语言中的每个小部件,您只有一个翻译。

谢谢。我很少看到回答者投票支持其他人的答案。谢谢Jim,生成的EF SQL更干净。@JimWooley您提到要使用SelectMany,但您的示例仅适用于SelectMany-我遗漏了什么吗?在封面下,来自。。。语法从转换为
。选择many
DbSet.Select(w => new
{
    Id = w.Id,
    Code = w.Code,
    LanguageId = languageId,
    Translation = w.WidgetTranslations
        .Where(wt => wt.LanguageId == languageId)
        .Select(wt => new
        {
            Name = wt.Name,
            Description = wt.Description,
            Summary = wt.Summary
        })
        .FirstOrDefault()
})
.AsEnumerable()
.Select(x => new TranslatedWidget
{
    Id = x.Id,
    Code = x.Code,
    LanguageId = x.LanguageId,
    Name = x.Translation != null ? x.Translation.Name : null,
    Description = x.Translation != null ? x.Translation.Description : null,
    Summary = x.Translation != null ? x.Translation.Summary : null
});
var widgetQuery = from w in dbSet.Widgets
                  from wt in w.WidgetTranslations
                  where wt.Language == languageId
                  select new TranslatedWidget
                  {
                     Id = w.Id,
                     Code = w.Code,
                     LanguageId = w.LanguageId,
                     Name = wt.Name,
                     Description = wt.Description,
                     Summary = wt.Summary
                  });