C# Include属性lambda表达式[…]无效。表达式应表示属性访问

C# Include属性lambda表达式[…]无效。表达式应表示属性访问,c#,entity-framework,linq,C#,Entity Framework,Linq,我正在尝试获取所有修补程序,并在可用属性为1的位置包含与之相关的所有详细信息。这是我的代码: public static IList<HotFix> GetAllHotFix() { using (Context context = new Context()) { return context.HotFix .Include(h => h.AssociatedPRs) .Include(h =&g

我正在尝试获取所有修补程序,并在可用属性为1的位置包含与之相关的所有详细信息。这是我的代码:

public static IList<HotFix> GetAllHotFix()
{
    using (Context context = new Context())
    {
        return context.HotFix
            .Include(h => h.AssociatedPRs)
            .Include(h => h.Detail.Where(d => d.Available = 1))
            .ToList();
    }
}
我发现了这个错误。我尝试了使用。但无法解决它

在修补程序内部,我有:

[Required]
public virtual List<HotFixDetail> Detail { get; set; }

尽管您忘记编写类定义,但似乎您有一个热修复程序类。每个修补程序都有一系列零个或多个关联的PRS和一系列零个或多个详细信息

Ever Detail至少有一个数值属性可用

您需要所有修补程序,每个修补程序都有其关联的PRS,以及所有属性可用值等于1的详细信息。您不是说可用值是一个布尔值吗

在使用实体框架时,人们倾向于使用include来获取包含子项的项。这并不总是最有效的方法,因为它获取表的完整行,包括您不打算使用的所有属性

例如,如果你有一对多的关系,学校和他们的学生,那么每个学生都会有一把该学生就读学校的外键

因此,如果学校[10]有1000名学生,那么每个学生都会有一个值为10的学校外键。如果使用Include获取学校[10]及其学生,则也会选择此外键值,并发送1000次。您已经知道它将等于Schools主键值,因此将此值传输10次1001次是对处理能力的浪费

查询数据时,请始终使用“选择”,并仅选择实际计划使用的属性。仅当您计划更新获取的数据时才使用Include

另一个好建议是用复数来描述序列,用奇数来描述序列中的一项

您的查询将是:

var result = context.HotFixes.Select(hotfix => new
{
    // Select only the hotfix properties you actually plan to use:
    Id = hotfix.Id,
    Date = hotfix.Date,
    ...

    AssociatedPRs = hotfix.AssociatedPRs.Select(accociatedPr => new
    {
        // again, select only the associatedPr properties that you plan to use
        Id = associatedPr.Id,
        Name = associatedPr.Name,
        ...

        // foreign key not needed, you already know the value
        // HotFixId = associatedPr.HotFixId
    })
    .ToList(),

    Details = hotfix.Details
        .Where(detail => detail.Available == 1)
        .Select(detail => new
        {
            Id = detail.Id,
            Description = detail.Description,
            ...

            // not needed, you know the value:
            // Available = detail.Available,

            // not needed, you know the value:
            // HotFixId = detail.HotFixId,
        })
        .ToList(),
});
我使用匿名类型。您只能在定义匿名类型的过程中使用它。如果需要返回提取的数据,则需要将所选数据放入类中

return context.HotFixes.Select(hotfix => new HotFix()
{
    Id = hotfix.Id,
    Date = hotfix.Date,
    ...

    AssociatedPRs = hotfix.AssociatedPRs.Select(accociatedPr => new AssociatedPr()
    {
       ... // etc
注意:您仍然不必填写所有字段,除非您的功能需求明确说明了这一点

函数的用户不知道哪些字段将实际填充,哪些字段将不填充,这可能会让人感到困惑。另一方面:当向数据库添加项时,它们已经习惯于不填充所有字段,例如主键和外键

为了解决这个问题,有些开发人员设计了一个额外的层:使用repository模式的repository层。为此,他们创建了一些类,这些类表示人们希望放入存储器并希望保存到存储器中的数据。通常,这些人对数据保存在关系数据库中(带有外键等)不感兴趣。因此存储库类将不具有外键

存储库模式的优点是,存储库层隐藏了存储系统的实际结构。它甚至隐藏了它是一个关系数据库。它也可能位于JSON文件中。如果数据库发生更改,存储库层的用户不必知道这一点,也可能不需要更改

存储库模式还使模拟数据库进行单元测试变得更容易:因为用户不知道数据在关系数据库中,所以对于单元测试,您可以将日期保存在JSON文件、CSV文件或其他文件中

缺点是您需要编写额外的类来保存要放入存储库或从存储库中提取的数据


添加这个额外的层是否明智,取决于您希望数据库在将来更改布局的频率,以及您的单元测试需要有多好。

尽管您忘记编写类定义,但似乎您有一个热修复类。每个修补程序都有一系列零个或多个关联的PRS和一系列零个或多个详细信息

Ever Detail至少有一个数值属性可用

您需要所有修补程序,每个修补程序都有其关联的PRS,以及所有属性可用值等于1的详细信息。您不是说可用值是一个布尔值吗

在使用实体框架时,人们倾向于使用include来获取包含子项的项。这并不总是最有效的方法,因为它获取表的完整行,包括您不打算使用的所有属性

例如,如果你有一对多的关系,学校和他们的学生,那么每个学生都会有一把该学生就读学校的外键

因此,如果学校[10]有1000名学生,那么每个学生都会有一个值为10的学校外键。如果使用Include获取学校[10]及其学生,则也会选择此外键值,并发送1000次。你已经知道它将与小学相等 y键值,因此将此值传输10 a 1001次是对处理能力的浪费

查询数据时,请始终使用“选择”,并仅选择实际计划使用的属性。仅当您计划更新获取的数据时才使用Include

另一个好建议是用复数来描述序列,用奇数来描述序列中的一项

您的查询将是:

var result = context.HotFixes.Select(hotfix => new
{
    // Select only the hotfix properties you actually plan to use:
    Id = hotfix.Id,
    Date = hotfix.Date,
    ...

    AssociatedPRs = hotfix.AssociatedPRs.Select(accociatedPr => new
    {
        // again, select only the associatedPr properties that you plan to use
        Id = associatedPr.Id,
        Name = associatedPr.Name,
        ...

        // foreign key not needed, you already know the value
        // HotFixId = associatedPr.HotFixId
    })
    .ToList(),

    Details = hotfix.Details
        .Where(detail => detail.Available == 1)
        .Select(detail => new
        {
            Id = detail.Id,
            Description = detail.Description,
            ...

            // not needed, you know the value:
            // Available = detail.Available,

            // not needed, you know the value:
            // HotFixId = detail.HotFixId,
        })
        .ToList(),
});
我使用匿名类型。您只能在定义匿名类型的过程中使用它。如果需要返回提取的数据,则需要将所选数据放入类中

return context.HotFixes.Select(hotfix => new HotFix()
{
    Id = hotfix.Id,
    Date = hotfix.Date,
    ...

    AssociatedPRs = hotfix.AssociatedPRs.Select(accociatedPr => new AssociatedPr()
    {
       ... // etc
注意:您仍然不必填写所有字段,除非您的功能需求明确说明了这一点

函数的用户不知道哪些字段将实际填充,哪些字段将不填充,这可能会让人感到困惑。另一方面:当向数据库添加项时,它们已经习惯于不填充所有字段,例如主键和外键

为了解决这个问题,有些开发人员设计了一个额外的层:使用repository模式的repository层。为此,他们创建了一些类,这些类表示人们希望放入存储器并希望保存到存储器中的数据。通常,这些人对数据保存在关系数据库中(带有外键等)不感兴趣。因此存储库类将不具有外键

存储库模式的优点是,存储库层隐藏了存储系统的实际结构。它甚至隐藏了它是一个关系数据库。它也可能位于JSON文件中。如果数据库发生更改,存储库层的用户不必知道这一点,也可能不需要更改

存储库模式还使模拟数据库进行单元测试变得更容易:因为用户不知道数据在关系数据库中,所以对于单元测试,您可以将日期保存在JSON文件、CSV文件或其他文件中

缺点是您需要编写额外的类来保存要放入存储库或从存储库中提取的数据


是否添加这个额外的层是明智的,取决于您希望数据库在将来更改布局的频率,以及您的单元测试需要有多好。

请发布热修复程序的代码,以及您无法筛选的热修复程序的详细信息,即,在include中使用Where不能共享太多,但我已将属性与列表一起添加到我的帖子中。如果它有价值的话,如果我移除了它工作正常但带来了所有details@DavidG有什么解决方法吗?那么你可能需要从HotFixDetail开始,然后回到HotFix。我不能使用HotFix.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Whered.Where。如果它有价值的话,如果我移除了它工作正常但带来了所有details@DavidG有什么解决方法吗?那么你可能需要从HotFixDetail开始,然后回到HotFix。比如context.HotFixDetail.Whered=>d.Available==1。。。。