英文:
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;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论