如何解决EF在导航属性为null时未抓取对象
我的问题是-如果数据库中的导航属性为“ null”,我的查询将不会返回我要查询的主要对象。
为清楚起见,我的问题不是.include()中的导航属性是否返回null。我的问题是属性IS应该为空,而当该属性为null时,则不会返回市场。
这是我的意思的示例:
我的代码:
markets = await _context.Markets
.Include(x => x.Agency)
.Include(x => x.Location)?.ThenInclude(x => x.State)?
.Include(x => x.Location).ThenInclude(x => x.Country)
.Where(x => x.Deleted == false
&& x.Agency.Deleted == false).ToListAsync();
我有一些市场,它们具有导航属性Location
,而导航属性又具有导航属性State
。对于某些Location
,State
为空。在State
模型中定义的Location
的外键是long?
。
但是,由于某种原因,不会在结果列表中返回“我的国家/地区为空”的市场,而是返回具有.Include()语句中包含的所有字段且不为null的实体。 / p>
我最初的代码中没有包含?
,但是包含...,例如:
.Include(x => x.Location).ThenInclude(x => x.State)
,但是没有用。我添加了可以为空的想法,尽管它没有帮助。
有人在这里有什么建议吗?运行此语句时,出现以下异常:
.SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
但是,异常不会中断流程,并且我得到的返回的对象没有空State
。
任何提示都将不胜感激!
编辑:
需要特别注意的是,当我所有的导航属性都不为null时,代码可以正常工作。当State为null(唯一可为null的导航属性)时,此问题就会出现。
型号:
public class Market
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long MarketId { get; set; }
[ForeignKey("Location")]
public long HeadquartersId { get; set; }
[Required]
public virtual Location Location { get; set; }
}
public class Location
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long LocationId { get; set; }
[ForeignKey("State")]
public long? StateId { get; set; }
[ForeignKey("Country")]
public long CountryId { get; set; }
[Required]
public virtual State State { get; set; }
[Required]
public virtual Country Country { get; set; }
}
解决方法
这是一个漫长的过程,但是请查看是否可以在DBContext的OnModelCreating
中手动配置这些关系。
示例:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Market>(a =>
{
a.HasOne(e => e.Location).WithMany().HasForeignKey(e => e.HeadquartersId).IsRequired(false);
});
builder.Entity<Location>(a =>
{
a.HasOne(e => e.State).WithMany().HasForeignKey(e => e.StateId).IsRequired(false);
a.HasOne(e => e.Country).WithMany().HasForeignKey(e => e.CountryId).IsRequired(false);
});
}
,
最终,问题出在我的位置模型中“状态”导航属性上的[Required]注释。
不幸的是,这是使用相同数据注释的Entity Framework和Blazor之间冲突的众多示例之一。
在我的示例中,State是必需的,因为Blazor中的表单验证需要State。但是,在我的数据库中,StateId实际上是一个可为空的外键,因为后端不一定需要它。
我已经提出了两种解决方法,如果您知道更好的解决方案,请随时添加其他解决方法。
-
为Blazor创建单独的前端模型,为EF创建后端模型。我知道,丑陋的重复代码。但是,这可以使关注点分离,并避免出现“此处需要,但不是此处”类型的问题。
-
在我的情况下,我还可以有一个单独的查询,首先检查我的国家(地区)。如果Country是某个值,则不会包含(x => x.State)。这是更具体的,但是对于某些已经存在无法大量更改的代码库的类似情况,可能是必需的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。