如何在我的LINQ中实现对数据库的单次调用
本文关键字:数据库 单次 调用 实现 我的 LINQ | 更新日期: 2023-09-27 18:20:33
我正在进行我的web API项目。
我在控制器类中有一行LinqToEntity:
SiteObject[] objects = await ObjectsRepository.Get().Where(x => x.SiteRegionId == regionId).ToArrayAsync();
return Ok(objects.Select(x => new ObjectBreif
{
IsServiceable = Context.InspectionReview.Any(i => i.ObjectId == x.Id && i.IsNormal == false) ? false : Context.InspectionReview.Any(i => i.ObjectId == x.Id) ? true : (bool?)null
})
我想创建比上面的行更有效的东西,而不是做两次数据库调用。
如果InspectionReview表中存在至少一行满足此条件条件:
ObjectId = 5 AND IsNormal = false
我需要将IsServiceable
设置为false
,否则,我需要检查InspectionReview表中是否存在具有以下条件的行:
ObjectId = 5
如果是,则IsServiceable
必须得到true
,否则为null
。
我通过使用上面的一行代码实现了这一点。但正如您所看到的,它并没有效果,因为我访问了两次数据库。
我不想为这个提议或额外的行创建额外的函数,因为我希望代码保持优雅。
试试这个:
var items = Context.InspectionReview.Where(i => i.ObjectID == x.id).ToList();
bool? IsServicable = (items.length == 0) ?
(bool?)null : !(items.Any(i => i.IsNormal == false));
知道代码中的objects
是什么很重要,但无论如何,现在开始:
带子查询
var result =
from x in objects
let AnyNormal = db.InspectionReview.Where(r => r.ObjectId == x.Id)
.DefaultIfEmpty().Min(r => r == null ? (int?)null : r.IsNormal ? 1 : 0)
select new ObjectBreif
{
IsServiceable = AnyNormal == null ? (bool?)null : AnyNormal == 1
};
或带有左侧外部连接
var result =
from x in objects
join r in db.InspectionReview on x.Id equals r.ObjectId into g
let AnyNormal = g.DefaultIfEmpty().Min(r => r == null ? (int?)null : r.IsNormal ? 1 : 0)
select new ObjectBreif
{
IsServiceable = AnyNormal == null ? (bool?)null : AnyNormal == 1
};
更新::现在,当您更新代码片段时,如果ObjectsRepository.Get
从数据库返回IQueryable<SiteObject>
(没有提前具体化),那么最好将两个查询组合成一个单独的查询,如
var result =
from x in ObjectsRepository.Get() where x.SiteRegionId == regionId
join r in db.InspectionReview on x.Id equals r.ObjectId into g
let AnyNormal = g.DefaultIfEmpty().Min(r => r == null ? (int?)null : r.IsNormal ? 1 : 0)
select new ObjectBreif
{
IsServiceable = AnyNormal == null ? (bool?)null : AnyNormal == 1
};
因为它将生成一个数据库查询,而所有其他数据库查询将对objects
数组中的每个项执行(好的,单个,而不是原始查询的两倍)查询。
编辑:由于ObjectId
不是唯一的:
var grouped = (from ir in Context.InspectionReview
group ir by ir.ObjectId into g
select new {
ObjectId = g.Key,
FalsePresent = g.Any(gg=>gg.IsNormal == false)}).FirstOrDefault();
if(grouped == null) return (bool?)null;
return !grouped.FalsePresent;
先按ObjectID
筛选,然后优先选择IsNormal
为false的:
var first = Context.InspectionReview
.Where(i => i.ObjectId == x.Id)
.OrderBy(i => IsNormal)
.FirstOrDefault();
bool? IsServiceable = (first == null) ? (bool?)null : first.IsNormal;