简体   繁体   English

包含路径表达式必须引用在类型上定义的导航属性(使用 LINQ 选择数据)

[英]The Include path expression must refer to a navigation property defined on the type (select data using LINQ)

I was trying to select data using LINQ and I have a list called "products" and I want just these items that exist in products list我试图使用 LINQ 获取 select 数据,我有一个名为“产品”的列表,我只想要产品列表中存在的这些项目

var Owner = db.Owners
  .Where(m => m.ID == id)
  .Include(m => m.Products.Where(item1 => products.Any(item2 => item2.ProductID == item1.ProductID)).ToList())
  .FirstOrDefault();

but I'm getting this error:但我收到此错误:

System.ArgumentException: 'The Include path expression must refer to a navigation property defined on the type. System.ArgumentException: '包含路径表达式必须引用在类型上定义的导航属性。 Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.对参考导航属性使用虚线路径,对集合导航属性使用 Select 运算符。 Parameter name: path'参数名称:路径'

Include is meant to fetch complete rows of a table, inclusive primary and foreign keys. Include 旨在获取表的完整行,包括主键和外键。

Usually it is not efficient to fetch the complete rows of a table.通常,获取表的完整行效率不高。 For example, suppose you have a database with Schools and Students.例如,假设您有一个包含学校和学生的数据库。 There is a one-to-many relation between Schools and Students: every School has zero or more Students, every Student attends exactly one School, namely the School that the foreign key refers to. Schools和Student之间存在一对多的关系:每个School有零个或多个Student,每个Student恰好就读一所School,即外键所指的School。

If you fetch School [10] with its 2000 Students, then every Student will have a foreign key SchoolId with a value 10. If you use Include and fetch complete Student rows you will transfer this value 10 over 2000 times.如果您获取包含 2000 个学生的 School [10],则每个 Student 都将有一个值为 10 的外键 SchoolId。如果您使用 Include 并获取完整的 Student 行,您将传输该值 10 超过 2000 次。 What a waste of processing power.多么浪费处理能力。

A DbContext has a ChangeTracker object. DbContext 有一个 ChangeTracker object。 Whenever you fetch data without using Select, so if you fetch complete rows, then the fetched rows are stored in the ChangeTracker, together with a Clone of it.每当您在不使用 Select 的情况下获取数据时,因此如果您获取完整的行,那么获取的行将与它的克隆一起存储在 ChangeTracker 中。 You get a reference to the Clone (or the original, doesn't matter).您会得到对克隆的引用(或原始的,没关系)。 When you change properties of the fetched data, you change the value in the Clone.当您更改获取数据的属性时,您会更改 Clone 中的值。 When you call SaveChanges , the values of all properties of all originals in the ChangeTracker are comparer with the values in the Clones.当您调用SaveChanges时,ChangeTracker 中所有原始文件的所有属性的值都与 Clone 中的值进行比较。 The items that are changed are updated in the database.更改的项目在数据库中更新。

So if you fetch School [10] with its Students, you are not only fetching way more data than you will ever use, but you will also store all these Students in the ChangeTracker together with a Cloned Student.因此,如果您获取 School [10] 及其学生,您不仅会获取比您将使用的更多的数据,而且您还会将所有这些学生与克隆学生一起存储在 ChangeTracker 中。 If you call SaveChanges for something completely different (the telephone number of the School for instance), then all Students are value compared property by property with their Clones.如果您为完全不同的东西(例如学校的电话号码)调用 SaveChanges,那么所有学生都将与他们的克隆进行逐个属性的值比较。

Whenever you fetch data using Entity Framework, always use Select , and Select only the properties that you actually plan to use.每当您使用 Entity Framework 获取数据时,请始终使用Select和 Select 仅使用您实际计划使用的属性。 Only fetch complete rows, only use Include if you plan to update the fetched data.仅获取完整行,仅在计划更新获取的数据时使用 Include。

Using Select will also solve your problem:使用 Select 也将解决您的问题:

int ownerId = ...
IEnumerable<Product> products = ...

var Owner = db.Owners.Where(owner => owner.ID == ownerId)
    .Select(owner => new
    {
        // Select only the Owner properties that you actually plan to use
        Id = owner.Id,
        Name = owner.Name,

        // get the Products of this Owner that are in variable products
        Products = owner.Products
            .Where(product => products.Any(p => p.ProductId == product.ProductId)
            .Select(product => new
            {
                // Select only the Product properties that you plan to use
                Id = product.Id,
                Price = product.Price,
                ...

                // No need to fetch the foreign key, you already fetched the value
                // OwnerId = product.OwnerId,
            })
            .ToList(),
        ...
    })
    .FirstOrDefault();

I used automatic types ( new {...} ).我使用了自动类型( new {...} )。 If you really want to create Owner and Properties, use:如果您真的想创建所有者和属性,请使用:

var Owner = db.Owners.Where(...)
.Select(owner => new Owner
{
    Id = owner.Id,
    ...

    Products = owner.Products.Where(...).Select(product => new Product
    {
        Id = product.Id,
        ...
    })
    .ToList(),
})
.FirstOrDefault();

this way it is not working split your query into 2 queries.这样就无法将您的查询拆分为 2 个查询。

var owner = db.Owners
    .Include(m => m.Products)
    .FirstOrDefault(m => m.ID == id);
if(owner != null)
{
var ownerProducts = owner.Products
  .Where(item1 => products.Any(item2 => item2.ProductID == item1.ProductID)).ToList();
}

maybe this way it works.也许这样就可以了。

Try the following:尝试以下操作:

var productIds = products.Select(x => x.ProductID);

var Owner = db.Owners
  .Where(m => m.ID == id)
  .Include(m => m.Products.Where(product => productIds.Contains(product.ProductID))
  .FirstOrDefault();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用LINQ查询三个实体。 -包含路径表达式必须引用在类型上定义的导航属性 - Using LINQ to query three entitites. - Include path expression must refer to a navigation property defined on the type Include路径表达式必须引用在类型上定义的导航属性。 - The Include path expression must refer to a navigation property defined on the type. EF:包含路径表达式必须引用在类型上定义的导航属性 - EF: The Include path expression must refer to a navigation property defined on the type 在include内使用where子句会产生错误“ include路径表达式必须引用在类型上定义的导航属性” - using where clause inside include generate error “The Include path expression must refer to a navigation property defined on the type” Include内的SingleOrDefault会引发以下错误:-Include路径表达式必须引用在类型上定义的导航属性 - SingleOrDefault inside Include will raise the following error :- The Include path expression must refer to a navigation property defined on the type 包含路径表达式必须引用定义的导航属性 - The Include path expression must refer to a navigation property defined 尝试解决“包含路径表达式必须引用在类型上定义的导航属性” - Trying to resolve “The Include path expression must refer to a navigation property defined on the type” 包含路径表达式必须引用在类型上定义的导航属性。 检索具有功能的产品时出错 - The Include path expression must refer to a navigation property defined on the type. Error when retrieving Products with Features 实体框架,“包含”路径表达式必须引用在类型上定义的导航属性 - Entity Framework, The Include path expression must refer to a navigation property defined on the type Include路径表达式必须引用在type.in eager loading上定义的导航属性 - The Include path expression must refer to a navigation property defined on the type.in eager loading
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM