c# - 带有关系实体的 LINQ 连接查询
问题描述
我正在使用 ef-core 2.1,我有以下简化实体,其中一个Account
映射到零个或多个Attribute
对象:
public class Account
{
public int Id { get; set; }
public int LongId { get; set; }
public List<Attribute> Attributes { get; set; }
}
public class Attribute
{
public int Id { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public Account Account { get; set; }
}
我有一个初始的字符串集合,类似于给Attribute.Value
定的固定.Attribute.Name
Attribute
Account
Attribute.Value
我想将 ef 实体与初始字符串集合分开,以便我可以轻松推断:
- 是否不
Account
存在对应对象或不Account
存在相关Attribute
对象(都等同于相同的用例)。 - 如果
Account
存在并且它包含所有必需的Attribute
对象,我想获得辅助的值Attribute
。
在没有 LINQ 和 ef 的情况下,我运行以下 SQL 查询,它忽略父级Account
并生成我想要的结果集:
CREATE TABLE #Temp
(
id nvarchar(20) not null
);
INSERT INTO #Temp (id) VALUES ('cejawq'), ('issokq'), ('cqlpjq'), ('mbgzvi'), ('wqwlff'), ('iedifh');
SELECT t.[Id], attr2.[Value]
FROM #Temp t
LEFT OUTER JOIN [dbo].[Attributes] attr1
ON t.[Id]=attr1.[Value]
AND attr1.[Name]='uid'
LEFT OUTER JOIN [dbo].[Attributes] attr2
ON attr1.[AccountId]=attr2.[AccountId]
AND attr2.[Name]='objType';
我得到以下结果集:
id|objType
-----------
cejawq|ext
issokq|ext
cqlpjq|int
mbgzvi|int
wqwlff|ext
iedifh|null
我正在努力将其映射到高效的 LINQ,以便生成的 SQL 远程生成结果集并将我可以投影到等效匿名类型的数据发回。我需要关心 LINQ 案例中的父对象吗?Attribute.Value
我在列上没有索引。
该Attributes
表包含以下数据:
Id|Name |Value |AccountId
1 |uid |cejawq|1
2 |objType|ext |1
3 |uid |issokq|2
4 |objType|ext |2
5 |uid |cqlpjq|3
6 |objType|int |3
7 |uid |mbgzvi|4
8 |objType|int |4
9 |uid |wqwlff|5
10|objType|ext |5
解决方案
由于 EF Core 不支持与内存序列中的连接(尚),因此您可以将查询分成两部分 - 一个将数据服务器端([Attributes
加入[Attributes
)使用内存集合作为过滤器(IN
通过 LINQContains
方法的 SQL),以及第二个使用 db 查询的结果在内存中执行左连接:
DbContext db = ...;
var uids = new [] { "cejawq", "issokq", "cqlpjq", "mbgzvi", "wqwlff", "iedifh" };
var dbQuery =
from attr1 in db.Set<Attribute>()
where attr1.Name == "uid" && uids.Contains(attr1.Value)
join attr2 in db.Set<Attribute>()
on new { AccountId = attr1.Account.Id, Name = "objType" }
equals new { AccountId = attr2.Account.Id, attr2.Name }
into attr2Group from attr2 in attr2Group.DefaultIfEmpty() // left outer join
select new { uid = attr1.Value, objType = attr2.Value };
var query =
from uid in uids
join dbResult in dbQuery on uid equals dbResult.uid
into dbResultGroup from dbResult in dbResultGroup.DefaultIfEmpty() // left outer join
select new { uid, dbResult?.objType };
var result = query.ToList();
它转换为像这样的单个数据库查询:
SELECT [attr1].[Value] AS [uid], [attr2].[Value] AS [objType]
FROM [Attributes] AS [attr1]
LEFT JOIN [Attributes] AS [attr2] ON ([attr1].[AccountId] = [attr2].[AccountId]) AND (N'objType' = [attr2].[Name])
WHERE ([attr1].[Name] = N'uid') AND [attr1].[Value] IN (N'cejawq', N'issokq', N'cqlpjq', N'mbgzvi', N'wqwlff', N'iedifh')
推荐阅读
- javascript - 如何在 Reactjs 材料 ui 中正确编写文本字段标签?
- windows - Windows 的 Docker 与 Windows Ubuntu 应用程序中的 Docker?
- javascript - 逻辑或运算符的输入文本字段问题
- sql - 如何从月表中计算月中位数?
- python - 使用 ssh 的树莓派 Python 安卓应用程序
- c# - 在服务器端为给定的 url 生成 pdf
- typo3 - 用于检查特定 list_type 是否在页面上的 TypoScript 条件
- javascript - 如何从用户输入而不是常量值开始计时器并保持我的会话存储仍在工作?
- php - PHP PDO mysql 查询同时使用 column = '$var' 和 column IS NULL
- c# - 在 Angular 中导入 excel 文件并将数据传递到 ASP.NET Core API 项目中