gpt4 book ai didi

c# - EF 将多个表合并为一个 IQueryable

转载 作者:太空狗 更新时间:2023-10-29 18:28:45 35 4
gpt4 key购买 nike

我正在使用 OData(WebAPI 和 EF)查询数据库。现在我必须将三个表“合并”为一个结果。

我有 3 个表和一个界面,如下所示:

public class Authority : IAssociationEntity
{
public string Name { get; set; }
public int AuthorityId { get; set; }
}

public class Company : IAssociationEntity
{
public string Name { get; set; }
public int CompanyId { get; set; }
}

public class Organization : IAssociationEntity
{
public string Name { get; set; }
public int OrganizationId { get; set; }
}

public interface IAssociationEntity
{
string Name { get; set; }
}

如您所见,这三个表之间有一些明显的相似之处,但出于某些原因,它们需要保留在单独的表中。我需要的是使用分页并按名称搜索所有三个,并将它们显示在同一个列表中以供用户使用。

我正在寻找在 SQL 中看起来像这样的东西

SELECT TOP 4 a.* FROM
(
SELECT CompanyID, Name from Company WHERE Name = 'Bob'
UNION
SELECT OrganizationID, Name from Organization WHERE Name = 'Bob'
UNION
SELECT AuthorityID, Name from Authority WHERE Name = 'Bob'
) AS a

有没有办法把三张表合二为一IQueryable

我想将这三个表合并成一个 IQueryable<IAssociationEntity> .我确实需要使用接口(interface)(或可能是基类)并将结果作为 IQueryable对于我的 OData 实现。像这样的东西,但它不编译:

var query = db.Companies
.Concat(db.Organizations)
.Concat(db.Authorities);
IQueryable<IAssociationEntity> mergedTables = query.Cast<IAssociationEntity>();

// Here is an EXAMPLE usage.
// What I really need is to return the IQueryable<IAssociationEntity> for my OData.
var result = mergedTables.Where(x => x.Name == "Bob").OrderBy(x => x.Name).Skip(2).Take(10);

以及我对 odata Controller 的使用:

public class AssociationController : ODataController
{
[EnableQuery]
public override IQueryable<IAssociationEntity> Get(ODataQueryOptions<IAssociationEntity> q)
{
// return my IQueryable here...
}
}

不用说,我不想在创建 IQueryable 时将整个表读入内存.实际上,我确实需要使用分页,因为这三个表中有几个表有数百万行。

最终解决方案如下:

  var query = db.Companies.Select(x => new AssociationEntity { Name = x.Name })
.Concat(db.Organizations.Select(x => new AssociationEntity { Name = x.Name }))
.Concat(db.Authorities.Select(x => new AssociationEntity { Name = x.Name }));
return query;

并且在针对可查询对象执行时:

_query.Where(x => x.Name.Contains("M")).OrderBy(x => x.Name).Skip(10).Take(50).ToList();

生成的 SQL:

SELECT 
[UnionAll2].[C1] AS [C1],
[UnionAll2].[Name] AS [C2]
FROM (SELECT
1 AS [C1],
[Extent1].[Name] AS [Name]
FROM [dbo].[Company] AS [Extent1]
WHERE [Extent1].[Name] LIKE N'%M%'
UNION ALL
SELECT
1 AS [C1],
[Extent2].[Name] AS [Name]
FROM [dbo].[Organization] AS [Extent2]
WHERE [Extent2].[Name] LIKE N'%M%'
UNION ALL
SELECT
1 AS [C1],
[Extent3].[Name] AS [Name]
FROM [dbo].[Authority] AS [Extent3]
WHERE [Extent3].[Name] LIKE N'%M%') AS [UnionAll2]
ORDER BY [UnionAll2].[Name] ASC
OFFSET 10 ROWS FETCH NEXT 50 ROWS ONLY

最佳答案

您必须使用 Class 而不是 Interface IAssociationEntity。我将其命名为 AssociationEntity

我已将您原来的TSQL 查询转换为:

SELECT TOP 4 a.* FROM
(
SELECT CompanyID, Name from Company WHERE Name = 'Bob'
UNION
SELECT OrganizationID, Name from Organization WHERE Name = 'Bob'
UNION
SELECT AuthorityID, Name from Authority WHERE Name = 'Bob'
) AS a

Linq To Entity Query,如下所示。

var queryKey ="Bob";

var query = ((from c in db.Company where (c.Name = queryKey) select new AssociationEntity { Name = c.Name }).Take(4))
.Concat((from o in db.Organization where (o.Name = queryKey) select new AssociationEntity { Name = o.Name }).Take(4))
.Concat((from a in db.Authority where (a.Name = queryKey) select new AssociationEntity { Name = a.Name }).Take(4));

关于c# - EF 将多个表合并为一个 IQueryable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39695922/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com