与LINQ一起进行实体投影的起订量

时间:2020-07-29 16:37:09

标签: c# .net linq linq-to-entities moq

我正在尝试将最小起订量集成到我的项目中,该项目将linq应用于实体-大部分情况下都可以按预期工作。我遇到的问题是当我投影到一个匿名对象时,该对象具有“ SQLizer”可以处理但MOQ引发异常的可空属性。

例如:

public class Person {
    public int Id {get;set;}
    public virtual void Car Car {get; set;}
}

public class Car {
   public int Id {get;set;}
}

public class Context {
   public DbSet<Car> Cars {get;set;}
   public DbSet<Person> People {get;set;}
}

// Just to show we have a person in the db without a car
context.People.Add(new Person{
   Id = 1,
});

// This throws an exception on MOQ, but works in SQL
context.People.Select(person => new {
   personId = person.Id,
   carId = (int?)person.Car.Id
});

我只想强调我遇到的问题,也许不是最佳的数据结构。关于如何处理的想法?最简单的方法是在投影之前检查null值,但我觉得可能有更好的选择。

1 个答案:

答案 0 :(得分:1)

使用上下文添加新的Person时,似乎跳过了添加Car实例并稍后尝试访问它的情况:

context.People.Select(person => new {
   personId = person.Id,
   carId = (int?)person.Car.Id // above you instantiated a Person without a Car instance
});

这里发生的是,在投射新元素期间,Select语句试图访问Car实例,而该实例根本不存在。

但是,如果您要拥有Person个实例,其中将不包含 Car更改代码以匹配以下两种方法之一:

第一个选项(使用null-coalescingnull-conditional运算符)

context.People.Select(person => new {
   personId = person.Id,
   carId = person.Car?.Id ?? 0 // 0 is the default value in case if Person doesn't have Car
});

第二个选项使用过滤

context.People.Where(p => p.Car != null).Select(person => new {
   personId = person.Id,
   carId = person.Car.Id
});
相关问题