繁体   English   中英

LINQ连接查询与关系实体

[英]LINQ join query with relational entities

我使用的是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实体,这样我就可以很容易地推断:

  1. 是否存在相应的Account或没有相关Attribute对象的Account (两者都等同于相同的用例)。
  2. 如果存在一个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连接],使用内存集合作为过滤器(SQL IN through LINQ Contains方法),第二个使用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')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM