1

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 上找到“名称”匹配,我真的不需要做“Generator = g”,反之亦然,如果我在 Generator 上找到它,我不需要做“BillTo = b”。

因此,如果有一种方法可以知道命中了哪个 WHERE 子句,那么我会将适当的 b 或 g 添加到结果中。我知道我可以在得到结果并重新检查我实际上作为 WHERE 子句发送的 7 个字段中的每一个之后重申,但这似乎是太多额外的代码。也许我的 LINQ 的调整是为了?是否有我可以通过反射或其他方法提取的值来找出被击中的内容?

4

2 回答 2

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();

所以你仍然返回相同的数据(正如评论所说,你可能实际上并不想要那些额外的布尔值,我只是把它们放在那里,因为它可能会简化你之后运行的任何控制流逻辑)但你只是分配如果布尔值匹配(我认为是)您的标准,则它们。如果不应该读取BillToandGenerator属性,则它们将是(我在这里假设了类型名称)。null

于 2012-05-01T20:57:03.553 回答
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)
)
于 2012-05-02T14:20:34.350 回答