question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Incorrect query generated by EF when using FullAuditedEntity

See original GitHub issue

I’m upgrading from Abp 0.9.0 to 3.2.4. Two queries that were working fine previously are failing now. The root cause appears to be the FullAuditedEntity base class.

The error being generated is: {"Unknown column 'Extent1.ParentId' in 'where clause'"}, which after checking the query executed, it’s not using the foreign keys to do the joins and is producing a query that doesn’t work.

Assume the following three classes:

public class GrandParent : FullAuditedEntity
    {
        public string Name { get; set; }
    }
public class Parent : FullAuditedEntity
    {
        public string Name { get; set; }
        public int GrandParentId { get; set; }
        public virtual GrandParent GrandParent { get; set; }
    }
public class Child : FullAuditedEntity
    {
        public string Name { get; set; }
        public int ParentId { get; set; }
        public virtual Parent Parent { get; set; }
    }

Pretty simple setup with a one to many relationship up the chain. Assume the following function to retrieve data from the Child repository:

var childQuery = _childRepository
                    .GetAll()
                    .Where(c => c.Parent.GrandParent.Name == "My Grandparent");
 var children = await childQuery.ToListAsync();

Because I’m navigating from Child to Parent and finally to GrandParent, you would think a simple join between the three entities would be used. It’s not and instead the produced query fails.

As a work around, removing FullAuditedEntity from the Parent class solves the issue.

Abp v3.2.4 .Net Framework v4.6.2 mySql.Data.Entity v6.9.11

EDIT:

Here’s the query generated when FullAuditedEntity is on:

SELECT `Apply1`.`Id`
	,`Apply1`.`Name`
	,`Apply1`.`ParentId`
FROM (
	SELECT `Extent1`.`Id`
		,`Extent1`.`Name`
		,`Extent1`.`ParentId`
		,(
			SELECT `Extent2`.`Id`
			FROM `GrandParents` AS `Extent2`
			INNER JOIN (
				SELECT `Extent3`.`Id`
					,`Extent3`.`Name`
					,`Extent3`.`GrandParentId`
					,`Extent3`.`IsDeleted`
					,`Extent3`.`DeleterUserId`
					,`Extent3`.`DeletionTime`
					,`Extent3`.`LastModificationTime`
					,`Extent3`.`LastModifierUserId`
					,`Extent3`.`CreationTime`
					,`Extent3`.`CreatorUserId`
				FROM `Parents` AS `Extent3`
				WHERE ((`Extent3`.`IsDeleted` = 0))
					AND (`Extent1`.`ParentId` = `Extent3`.`Id`) LIMIT 1
				) AS `Limit1` ON `Limit1`.`GrandParentId` = `Extent2`.`Id`
			WHERE (`Extent2`.`IsDeleted` = 0) LIMIT 1
			) AS `ID1`
		,(
			SELECT `Extent2`.`Name`
			FROM `GrandParents` AS `Extent2`
			INNER JOIN (
				SELECT `Extent3`.`Id`
					,`Extent3`.`Name`
					,`Extent3`.`GrandParentId`
					,`Extent3`.`IsDeleted`
					,`Extent3`.`DeleterUserId`
					,`Extent3`.`DeletionTime`
					,`Extent3`.`LastModificationTime`
					,`Extent3`.`LastModifierUserId`
					,`Extent3`.`CreationTime`
					,`Extent3`.`CreatorUserId`
				FROM `Parents` AS `Extent3`
				WHERE ((`Extent3`.`IsDeleted` = 0))
					AND (`Extent1`.`ParentId` = `Extent3`.`Id`) LIMIT 1
				) AS `Limit1` ON `Limit1`.`GrandParentId` = `Extent2`.`Id`
			WHERE (`Extent2`.`IsDeleted` = 0) LIMIT 1
			) AS `NAME1`
		,(
			SELECT `Extent2`.`IsDeleted`
			FROM `GrandParents` AS `Extent2`
			INNER JOIN (
				SELECT `Extent3`.`Id`
					,`Extent3`.`Name`
					,`Extent3`.`GrandParentId`
					,`Extent3`.`IsDeleted`
					,`Extent3`.`DeleterUserId`
					,`Extent3`.`DeletionTime`
					,`Extent3`.`LastModificationTime`
					,`Extent3`.`LastModifierUserId`
					,`Extent3`.`CreationTime`
					,`Extent3`.`CreatorUserId`
				FROM `Parents` AS `Extent3`
				WHERE ((`Extent3`.`IsDeleted` = 0))
					AND (`Extent1`.`ParentId` = `Extent3`.`Id`) LIMIT 1
				) AS `Limit1` ON `Limit1`.`GrandParentId` = `Extent2`.`Id`
			WHERE (`Extent2`.`IsDeleted` = 0) LIMIT 1
			) AS `IsDeleted`
		,(
			SELECT `Limit1`.`GrandParentId`
			FROM `GrandParents` AS `Extent2`
			INNER JOIN (
				SELECT `Extent3`.`Id`
					,`Extent3`.`Name`
					,`Extent3`.`GrandParentId`
					,`Extent3`.`IsDeleted`
					,`Extent3`.`DeleterUserId`
					,`Extent3`.`DeletionTime`
					,`Extent3`.`LastModificationTime`
					,`Extent3`.`LastModifierUserId`
					,`Extent3`.`CreationTime`
					,`Extent3`.`CreatorUserId`
				FROM `Parents` AS `Extent3`
				WHERE ((`Extent3`.`IsDeleted` = 0))
					AND (`Extent1`.`ParentId` = `Extent3`.`Id`) LIMIT 1
				) AS `Limit1` ON `Limit1`.`GrandParentId` = `Extent2`.`Id`
			WHERE (`Extent2`.`IsDeleted` = 0) LIMIT 1
			) AS `GrandParentId`
	FROM `Children` AS `Extent1`
	) AS `Apply1`
WHERE 'My Grandparent' = `Apply1`.`NAME1`

And here’s the query generated after removing the FullAuditedEntity:

SELECT `Extent1`.`Id`
	,`Extent1`.`Name`
	,`Extent1`.`ParentId`
FROM `Children` AS `Extent1`
INNER JOIN `Parents` AS `Extent2` ON `Extent1`.`ParentId` = `Extent2`.`Id`
INNER JOIN `GrandParents` AS `Extent3` ON `Extent2`.`GrandParentId` = `Extent3`.`Id`
WHERE 'My Grandparent' = `Extent3`.`Name`

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:16 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
ryancyqcommented, Aug 8, 2020

@thibnes could you open a new issue and stating the problems, Abp version, Ef6/EfCore version, etc…

0reactions
thibnescommented, Aug 7, 2020

@Lefka as an alternative, you can override onModelCreating of your DbContext and change it’s content to something like below;

base.OnModelCreating(modelBuilder);
//modelBuilder.Filter(AbpDataFilters.SoftDelete, (ISoftDelete d) => d.IsDeleted, false);
modelBuilder.Filter(AbpDataFilters.MustHaveTenant,
	(IMustHaveTenant t, int tenantId) => t.TenantId == tenantId || (int?) t.TenantId == null,
	0); //While "(int?)t.TenantId == null" seems wrong, it's needed. See https://github.com/jcachat/EntityFramework.DynamicFilters/issues/62#issuecomment-208198058
modelBuilder.Filter(AbpDataFilters.MayHaveTenant,
	(IMayHaveTenant t, int? tenantId) => t.TenantId == tenantId, 0);

But currently it will call the AbpDbContext’s OnModelCreating again and soft delete filter will be added. I will seperate filter configuration into anohter method and you can override it when ABP v3.6 is released. Related issue #3241.

After that, you can filter soft delete entities in GetAll method of your base repository.

Hi @ismcagdas I tried to remove the SoftDelete filter as you suggested however it leads me to a System.ApplicationException: ‘Filter name SoftDelete not found’ It looks like the filter is still registered. Is there a way to bypass that?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Wrong Query Generated with EF Core 3.0
I am trying to use a simple where clause to retrieve data from a SQL Server. However the generated query is incorrect.This query...
Read more >
SQL Queries - EF Core
Entity Framework Core allows you to drop down to SQL queries when working with a relational database. SQL queries are useful if the...
Read more >
Views and Incorrect Data in Entity Framework - Dustin Horne
In this particular case, EF generates the View in the EDMX and sets all columns as an entity key. Querying the entire list...
Read more >
Efficient Querying - EF Core
Performance guide for efficient querying using Entity Framework Core.
Read more >
Common Entity Framework Problems: N + 1
The problem is that in our original query we're not getting data from the LinkedPosts entity, just data from Posts and PostTags. Entity...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found