gpt4 book ai didi

c# - 以编程方式更改 Select 中的属性在 LINQ to SQL 查询中的填充方式

转载 作者:太空宇宙 更新时间:2023-11-03 11:49:59 27 4
gpt4 key购买 nike

我正在编写一些 LINQ to SQL,它需要在我们的数据库中搜索客户信息,过滤结果并对它们进行分页。过滤需要是动态的,所以我将查询的设置分为四个阶段:

  1. 寻找可见客户(基本上应用粗粒度过滤器)
  2. 按搜索条件过滤客户
  3. 对客户进行分类和分页
  4. 检索其他客户数据

代码如下:

// Step 1
var visibleClientQuery = from x in xs
from y in ys
from z in yas
where
...
select new
{
id = z.Client.Id,
a = z.Client.a,
b = z.Client.e.f.g.b
};

// Step 2
if (filterByA)
{
visibleClientQuery = visibleClientQuery.Where(client => client.a > 10);
}
else
{
visibleClientQuery = visibleClientQuery.Where(client => client.b.StartsWith("ABC"));
}

// Step 3
visibleClientQuery = visibleClientQuery.Distinct();

if (filterByA)
{
visibleClientQuery = visibleClientQuery.OrderBy(client => client.a);
}
else
{
visibleClientQuery = visibleClientQuery.OrderBy(client => client.b);
}

visibleClientQuery = visibleClientQuery.Skip(50).Take(30);

// Step 4
var fullQuery = from filterClientDetail in filteredClientQuery
join client in Clients on filterClientDetail.Id equals client.Id
...;

LINQ to SQL 可以很好地将这些元素组合在一起以生成高效的查询。但我想做的一件事是减少在第一个粗略查询中创建的连接数。如果我按 A 过滤和排序,则第一个查询不需要使用以下行填充 b:

b = z.Client.e.f.g.b

不填充 b 将节省所有额外的连接。我尝试用以下内容替换该行:

b = filterByA ? string.Empty : z.Client.e.f.g.b

虽然这在功能上有效,但当 filterByA 为真时,多余的连接仍然存在于查询中……减慢了速度。我的解决方法是引入另一个包含步骤 1 查询的临时查询:

// Step 1
var visibleClientQuery = from x in xs
from y in ys
from z in yas
where
...
select z.Client;

// Step 2
var filteredClientQuery = from client in visibleClientQuery
select new
{
id = client.Id,
a = client.a,
b = string.Empty
};

然后如果我们需要按 B 过滤,则替换为:

filteredClientQuery = from client in visibleClientQuery
select new
{
id = client.Id,
a = 0,
b = client.e.f.g.b
};

只要替换查询返回一个具有相同属性的匿名类,这就可以工作,但似乎是一个不必要的、重量级的 hack,并且不允许简单地混合和匹配过滤器……如果我们需要过滤甲乙?真正的查询还有几个可能的过滤器。

是否有任何方法可以通过编程方式更改单个属性在从查询返回的匿名类中的填充方式...与可以更改 where 子句的方式大致相同?使用 filteredClientQuery.Select(...) 我可以换出整个选择,但我看不到处理单个属性的方法。

感谢任何帮助...即使只是确认没有解决方案!

最佳答案

您应该尽可能多地针对映射类编写查询。交出控制权。

编辑:不要让匿名类型声明限制您的思维。随意声明一个自定义类型来保存自定义结果。毕竟,匿名类型只是让编译器为您创建/命名类型。

public class SubClient
{
public int id {get;set;}
public int? a {get;set;}
public string b {get;set;}
}


// Step 1
IQueryable<Client> visibleClientQuery =
from x in xs
from y in ys
from z in yas
where
...
select z.Client;

IQueryable<SubClient> subClientQuery = null;

// Step 2
if (filterByA)
{
subClientQuery = visibleClientQuery.Select(c => new SubClient()
{
id = c.id,
a = c.a
}).Where(x => x.a > 10);
}
else
{
subClientQuery = visibleClientQuery.Select(c => new SubClient()
{
id = c.id,
b = c.e.f.g.b
})
.Where(x => x.b.StartsWith("ABC"));
}

// Step 3
subClientQuery = subClientQuery.Distinct();

if (filterByA)
{
subClientQuery = subClientQuery.OrderBy(c => c.a);
}
else
{
subClientQuery = subClientQuery.OrderBy(c => c.b);
}

subClientQuery = subClientQuery.Skip(50).Take(30);

编辑:回复评论的奖金。

如果你想要一个Func<Client, string> ,你可以这样理解:

Func<Client, string> func = c => c.e.f.g.b;

如果你想要一个 Expression ,这样做(编译器会处理)。

Expression<Func<Client, string>> expr = c => c.e.f.g.b;

实际上我的代码中有这一行,直到我意识到很难在 Where 调用中使用它。也许你能弄明白。


Expression<Func<Client, SubClient>> selectExpr =
GetSelectExpressionForFilterCriteria(filterByA, filterByB,
filterByC, filterByD, filterByE);

Expression<Func<SubClient, bool>> filterExpr =
GetFilterExpressionForFilterCriteria(filterByA, filterByB,
filterByC, filterByD, filterByE);

subClientQuery = clientQuery.Select(selectExpr).Where(filterExpr);

关于c# - 以编程方式更改 Select 中的属性在 LINQ to SQL 查询中的填充方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2367514/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com