LINQ中有没有办法告诉哪个WHERE子句命中?我有一个名为Company的对象,它可以反过来拥有多个BillTo对象,每个BillTo对象可以有多个Generator对象。
Company
|
+-- BillTo1 - named First
| |
| |-- Generator1 - named Alpha
| |
| +-- Generator2 - named Beta
|
+-- BillTo2 - named Second
|
+-- Generator3 - name Gamma
这是linq语句(为其他where语句删除了额外的东西):
bool HaveCompany = !string.IsNullOrWhiteSpace(Company);
var AllData = (from co in db.Companies
join bt in db.Billtoes on co.ID equals bt.CompanyID into bts
from b in bts.DefaultIfEmpty()
join gn in db.Generators on b.ID equals gn.BillToID into gns
from g in gns.DefaultIfEmpty()
where co.Active == true
&& (
co.Name.Contains(HaveCompany ? Company : co.Name) ||
b.Name.Contains(HaveCompany ? Company : b.Name) ||
g.Name.Contains(HaveCompany ? Company : g.Name)
)
select new {
CompanyID = co.ID,
BillTo = b,
Generator = g,
Name = co.Name,
}).ToList();
问题是,它找到了正确的一切。如果我在BillTo上找到“Name”匹配,我不需要做“Generator = g”,反之亦然,如果我在Generator上找到它我不需要做“BillTo = b”。< / p>
因此,如果有办法知道哪个WHERE子句被击中,那么我会在结果中添加适当的b或g。我知道我可以通过AFTER得到结果重新检查并重新检查我实际发送的7个字段中的每一个作为WHERE子句,但这似乎是太多额外的代码。也许我的LINQ的调整是有序的?是否有我可以通过反射或某些东西提取的值来找出被击中的内容?
答案 0 :(得分:3)
你必须决定 - 你想要三个选择分支(实际上它应该是我认为的两个嵌套?:
语句)?或者您想选择一个拥有所有潜在成员的对象?就个人而言,为避免在select
语句中使用具体类型,或使用dynamic
,我只想扩展您的匿名类型:
您可以使用let
进行一次Contains
检查,然后在where
子句和匿名类型成员的分配中使用这些检查:
/* .... */
let coContains = co.Name.Contains(HaveCompany ? Company : co.Name)
let bContains = b.Name.Contains(HaveCompany ? Company : b.Name)
let gContains = g.Name.Contains(HaveCompany ? Company : g.Name)
where co.Active == true
&& ( coContains || bContains || gContains )
select new {
/* sticking the booleans on there as well - might not want to do that */
CoContains = coContains,
BContains = bContains,
GContains = gContains,
/* other properties as per your code example */
CompanyID = co.ID,
BillTo = !gContains && bContains ? b : (BillTo)null,
Generator = gContains && !bContains ? g : (Generator)null,
Name = co.Name
}).ToList();
所以你仍然会返回相同的数据(因为评论说你可能实际上并不想要那些额外的数据
布尔,我只是把它们放在那里,因为它可能会简化你之后运行的任何控制流逻辑)但是你只是在布尔符合(我认为是)你的标准的情况下分配它们。 BillTo
和Generator
属性将为null
(我在此处假设类型名称),如果它们不应被读取。
答案 1 :(得分:0)
如果您确定符合哪个条件,则可能是对数据进行分区而不是对其进行过滤。分区是GroupBy的工作。然后你可以根据键进行条件组投影。
.GroupBy(x => x.co.Name.Contains(HaveCompany ? Company : co.Name) ? 1 :
x.b.Name.Contains(HaveCompany ? Company : b.Name) ? 2 :
x.gen.Name.Contains(HaveCompany ? Company : gen.Name) ? 3 :
0
)
.SelectMany(g =>
g.Key == 1 ? g.Select(x => new {
CompanyID = x.co.ID,
BillTo = x.b,
Generator = x.gen,
Name = co.Name
} :
g.Key == 2 ? g.Select(x => new {
CompanyID = co.ID,
BillTo = b,
Generator = (Generator) null,
Name = co.Name
} :
g.Key == 3 ? g.Select(x => new {
CompanyID = co.ID,
BillTo = (BillTo) null,
Generator = gen,
Name = co.Name
} :
g.Where(x => false)
)