从相同 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)
我有一个 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)