首页 > 解决方案 > 获取子列表可以为空的列表项

问题描述

嗨,我有一种情况,我有一辆汽车,汽车有很多定制,定制可能有很多版本。

如果它具有 versionName 包含“xyz”的版本,我正在尝试获取汽车定制。

var customizationToBeUpdated = car.Customizations.FirstOrDefault(pv =>
                    pv.Versions.Any(ver =>
                        ver.Name.Contains("xyz")));

上面的代码在找到匹配的版本时有效,但如果找不到则抛出异常。关于如何处理此案的任何建议都无效?

异常: System.NullReferenceException:对象引用未设置为对象的实例。

干杯

标签: entity-frameworklinq

解决方案


要求

你写了:

如果它具有 versionName 包含“xyz”的版本,我正在尝试获取汽车定制。

“汽车定制?汽车是否只有一个具有此版本名称的定制?

  • A车有三种定制:K、L、M
  • K 有一个版本:“1.0”
  • L 有两个版本:“1.0”和“2.0”
  • M 有三个版本:“1.0”“1.1”“2.0”

给我“1.0”版本的汽车 A 的“定制”。

课程

唉,你忘了给我们上课。如果您遵循实体框架代码优先约定,您将拥有如下类:

class Car
{
    public int Id {get; set;}
    ... // other properties

    // Every Car has zero or more Customizations (one-to-many)
    public virtual ICollection<Customization> Customizations {get; set;}
}

class Customization
{
    public int Id {get; set;}
    ... // other properties

    // Every Customization belongs to exactly one Car, using foreign key
    public int CarId {get; set;}
    public virtual Car Car {get; set;}

    // Every Customization has zero or more Versions (one-to-many)
    public virtual ICollection<Version> Versions {get; set;}
}

class Version
{
    public int Id {get; set;}
    public string Name {get; set;}
    ... // other properties

    // Every Version belongs to exactly one Customization, using foreign key
    public int CustomizationId {get; set;}
    public virtual Customization Customization {get; set;}
}

这就是实体框架检测一对多关系所需的全部内容。

在实体框架中,表的列使用非虚拟属性表示;虚拟属性表示表之间的关系(一对多,多对多,...)

因此外键是非虚拟的;外键所指的对象是虚拟的。

回到你的问题

要求:给定 acar和 a versionName,给我Customizations这辆至少Version有一个Name等于这个的汽车VersionName

Car car = ...
string versionName = ...

您可以从自定义或版本开始:

从定制开始:给我我的汽车的定制,它至少有一个名称等于 versionName 的版本:

var result = dbContext.Customizations
    .Where(customization => 
        // it is one of the customization of my car:
        customization.CarId == car.Id

        // and this customization has at least one Version with versionName:
        customization.Versions.Where(version => version.Name == versionName))
                              .Any());

您还可以从版本开始:从名称等于 versionName 和我的汽车的自定义的每个版本中,给我一些自定义属性:

var result = dbContext.Versions

    // keep only the Versions that have the correct VersionName
    // and that is a Customization of my car:
    .Where(version => version.Name == versionName
                   && version.Customization.CarId == car.Id)

    // from the remaining Versions Select the properties that you plan to use
    .Select(version => new
    {
         // Select the Customization properties that you want:
         Id = version.Customization.Id,
         CustomizationCode = version.Customization.Code,
         ...
    });

推荐阅读