Linq查询使用.NET、LinqToDB和Postgresql上的可选表联接。

huangapple go评论51阅读模式
英文:

Linq query with optional join on table using .NET, LinqToDB & Postgresql

问题

以下是要翻译的内容:

What I want to accomplish;

A scout can create reports. The scout is the creator of the report.
We display the reports that this scout has created in a table.
The very same scout can be given access to a report that someone else has created.
All reports that this scout has access to should be displayed in the same table.

Tech stack

.NET 7 (LinqToDB), Postgresql

Database structure:

Table 1; "Reports".
Columns; Id, CreatedBy

Table 2; "ReportAccess"
Columns; ReportId, ScoutId

The linq query

Here's a sample of how I can get those reports that I have been given access to;

var query = from p in db.Reports
	 join c in db.ReportAccess on p.Id equals c.ReportId
	 where c.ScoutId == scoutId
	 select p;

and here's a sample of how I can get those reports that I have created;

var query = from p in db.Reports
	 where c.CreatedBy == scoutId
	 select p;

The question

How does one merge the two linq queries with an OR clause so only one query is made towards the db? I want to be able to use paging (take/skip) functionality, therefore the need of a single query.

I've tried to find examples without any luck.

I understand that I should probably start by creating an SQL query that later is transformed into linq syntax. I am not aware of how to create the SQL query.

英文:

What I want to accomplish;

A scout can create reports. The scout is the creator of the report.
We display the reports that this scout has created in a table.
The very same scout can be given access to a report that someone else has created.
All reports that this scout has access to should be displayed in the same table.

Tech stack

.NET 7 (LinqToDB), Postgresql

Database structure:

Table 1; "Reports".
Columns; Id, CreatedBy

Table 2; "ReportAccess"
Columns; ReportId, ScoutId

The linq query

Here's a sample of how I can get those reports that I have been given access to;

var query = from p in db.Reports
	 join c in db.ReportAccess on p.Id equals c.ReportId
	 where c.ScoutId == scoutId
	 select p;

and here's a sample of how I can get those reports that I have created;

var query = from p in db.Reports
	 where c.CreatedBy == scoutId
	 select p;

The question

How does one merge the two linq queries with an OR clause so only one query is made towards the db? I want to be able to use paging (take/skip) functionality, therefore the need of a single query.

I've tried to find examples without any luck.

I understand that I should probably start by creating an SQL query that later is transformed into linq syntax. I am not aware of how to create the SQL query.

答案1

得分: 1

你可以使用左连接(LEFT JOIN)来执行这样的查询:

var query = 
    from p in db.Reports
    from c in db.ReportAccess
        .Where(c => c.ReportId == p.Id && c.ScoutId == scoutId)
        .DefaultIfEmpty()
    where c != null || c.CreatedBy == scoutId
    select p;

或者使用 Any 运算符。但要确保执行计划不会变得更差:

var query = 
    from p in db.Reports
    where c.CreatedBy == scoutId || 
        db.ReportAccess.Any(c => c.ReportId == p.Id && c.ScoutId == scoutId)
    select p;
英文:

You can use LEFT JOIN for such query:

var query = 
    from p in db.Reports
	from c in db.ReportAccess
        .Where(c => c.ReportId == p.Id && c.ScoutId == scoutId)
        .DefaultIfEmpty()
	where c != null || c.CreatedBy == scoutId
	select p;

Or Any operator. But ensure that execution plan is not worse:

var query = 
    from p in db.Reports
	where c.CreatedBy == scoutId || 
        db.ReportAccess.Any(c => c.ReportId == p.Id && c.ScoutId == scoutId)
	select p;

huangapple
  • 本文由 发表于 2023年7月20日 17:19:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728398.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定