【发布时间】:2018-01-07 07:47:03
【问题描述】:
我有一个包含两个实体的简单模型:
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(150)] public string Name { get; set; }
}
public class Order
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public decimal? Amount { get; set; }
public int? ProductId { get; set; }
[ForeignKey(nameof(ProductId))] public Product Product { get; set; }
}
public class OrderContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Order> Orders { get; set; }
}
如您所见,Order 和 Product 之间有一个可为空的外键。
我用这些记录初始化了数据库:
using (var db = new OrderContext())
{
var p = new Product {Name = "Test"};
db.Products.Add(p);
db.Orders.Add(new Order {Product = p, Amount = 1});
db.Orders.Add(new Order {ProductId = null, Amount = 2});
db.SaveChanges();
}
当我执行以下查询时,会引发 InvalidOperationException:
var result = db.Orders.GroupBy(x => x.Product.Id).ToArray();
异常信息是:
System.InvalidOperationException:转换为值类型“System.Int32”失败,因为具体化值为 null。结果类型的泛型参数或查询必须使用可为空的类型。
这是 EF 中的错误吗?如何解决?
--
这不是The cast to value type 'Int32' failed because the materialized value is null 的重复。尽管有相同的异常信息,但问题的原因和解决方法却完全不同。提到的问题是关于聚合一个空集合。但这是关于按另一个左连接表的主键进行分组。我不知道这两个问题为什么会如此相似!
【问题讨论】:
-
会有没有产品或金额的订单吗?如果不是,为什么这些道具可以为空?
-
尝试从
x => x.Product.Id更改为x => x.ProductId- 这可能会解决问题,虽然我同意,但 EF 应该能够处理这种情况 -
执行以下操作...
var orders = db.Orders.ToArray();和var products = db.Products.ToArray();? -
“我不知道这两个问题为什么会如此相似!” - 因为它们只是同一个潜在问题的两种不同表现形式,正如另一个问题的答案所解释的那样。我暂时不会再次关闭它,因为您写的是“问题的原因和解决方案完全不同”。其他问题的公认答案应该也适合您。你真的是说
db.Orders.GroupBy(x => (int?)x.Product.Id)仍然给你一个例外吗? -
@Khodaie 我不猜测他们可能只是基于相同的异常消息在这里有相同的潜在问题,我是说他们在这里肯定有相同的潜在问题,那就是C# 类型规则和 SQL 可空性规则在某些情况下具有根本不同的行为,C# 类型规则在编译时使用,但 SQL 可空性规则在运行时使用。由于您现在确认其他问题的答案实际上在这里有效,与您的编辑建议相反,是否可以再次关闭此问题?
标签: c# entity-framework