从相同 table 过滤数据时出现问题

Problem in filtering the data from the same table

我有一个 class 如下所示:

 public class MasterTransaction 
    {
        public int Id { get; set; }
        public int EmployeeId { get; set; }
        public int? SubTransactionId { get; set; }

        [ForeignKey("SubTransactionId")]
        public virtual MasterTransaction SubTransaction { get; set; }
        public virtual ICollection<CommissionForManager> CommissionForManager { get; set; }
    }
    
    public class CommissionForManager
    {
        public int Id { get; set; }
        public int ManagerId { get; set; }
        public decimal CommissionMoney { get; set; }
        
         public int MasterTransactionId { get; set; }

        [ForeignKey("MasterTransactionId")]
        public virtual MasterTransaction MasterTransaction { get; set; }
    }

MasterTransaction 将存储所有主交易。 CommissionForManager table 存储与经理从中获得佣金的所有交易相关的数据。

示例数据:

MasterTransaction:

Id   EmployeeId     SubTransactionId
50   100            null  //100 is normal employee            
51   101            50    //101 is a Manager
52   102            null


CommissionForManager:

Id  ManagerId   CommissionMoney MasterTransactionId
1   101         5000            50  
2   101         6000            52  

现在经理从员工的交易创建交易,在这种情况下,“SubTransactionId”列将保存该交易的 TransactionId

例如:经理 101 从交易 50 创建了交易,因此 SubTransactionId 持有值 50。

所以我想获取经理获得佣金的交易列表,但不应在“SubTransactionId”列中引用这些特定交易。

例如: 事务 ID = 50 和 51 因为 51 是从 50 创建的,所以我想忽略两者。我只想要事务 52,因为它没有在另一个事务的“SubTransactionId”列中被引用。

查询:

string searchString;
int managerId;
var query = context.CommissionForManager.Where(c => c.CommissionMoney > 0)
                                        .Where(c=> c.MasterTransaction.Employee.EmployeeName.Contains(searchString));
                                        
if (managerId > 0)
    query = query.Where(c=>c.ManagerId == managerId);
    
return query.ToList();
    

但是在这里,我不知道如何在同一个 MasterTransaction 的 SubTransactionId 中再次搜索 Transaction Id table?

有人可以帮助我或指导我完成:)

这将 select MasterTransaction 的 SubTransactionId 列中出现 MasterTransactionId 的 CommissionForManager 中没有行

var query = context.CommissionForManager.Where(c => c.CommissionMoney > 0)
    .Where(c=> c.MasterTransaction.Employee.EmployeeName.Contains(searchString))
    .Where(c => !context.MasterTransaction.Where(row => row.SubTransactionId == c.MasterTransactionId).Any());

此代码将执行与上面相同的操作,但生成左外连接而不是嵌套 select:

            var query = from c in context.CommissionForManagers
                     join m in context.MasterTransactions on c.MasterTransactionId equals m.SubTransactionId
                     into joined from j in joined.DefaultIfEmpty()      // Without this a inner join will be performed instead of a left join
                     where c.CommissionMoney > 0
                     && j == null                   // Select only rows that havent been joined to a MasterTransactions row by SubTransactionId
                     //&& c.MasterTransactions.Employee.EmployeeName.Contains(searchString)
                     select c;

生成SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[ManagerId] AS [ManagerId], 
[Extent1].[CommissionMoney] AS [CommissionMoney], 
[Extent1].[MasterTransactionId] AS [MasterTransactionId]
FROM  [dbo].[CommissionForManager] AS [Extent1]
LEFT OUTER JOIN [dbo].[MasterTransaction] AS [Extent2] ON ([Extent1].[MasterTransactionId] = [Extent2].[SubTransactionId]) OR (([Extent1].[MasterTransactionId] IS NULL) AND ([Extent2].[SubTransactionId] IS NULL))
WHERE ([Extent1].[CommissionMoney] > 0) AND ([Extent2].[Id] IS NULL)
  • but those particular transactions shouldn't be referenced in "SubTransactionId" column

  • For ex: Transaction Id = 50 and 51 because 51 is created from 50 so I want to ignore both

第二个并不完全符合第一个要求。另外,SubTransactionId 的名称选择不当,因为它给人的印象是指向某些 child 的指针(引用),而实际上它似乎有 parent 引用语义。

因此,如果第二个陈述是正确的,则要求可以表述如下:"仅包括具有 (1) 没有父级 ( 2) 没有子事务.

第一个条件很容易通过导航属性检查,另一个需要在相应的DbSet上进行子查询(记住它是可查询的,所以在LINQ中解析为table访问到实体查询)。

例如(跳过应用其他过滤器的初始部分)

query = query.Where(c =>
    c.MasterTransaction.SubTransctionId == null // (1)
    &&
    !context.Set<MasterTransaction>().Any(t => t.SubTransactionId == c.MasterTransactionId) // (2)
);

问题的 dilemma/issue 似乎是因为模型中缺少反向导航 属性。如果你有它(你应该这样做,因为它有助于更​​好地理解关系并 属性 从双方查询它),例如

public class MasterTransaction 
{
    // ...
    public virtual ICollection<MasterTransaction> ChildTransactions { get; set; }
}

那么第二个条件就是

!c.MasterTransaction.ChildTransactions.Any() // (2)