c# - LINQ查询不同的集合具有相同的逻辑

标签 c# .net linq collections

这个问题困扰了我一段时间,让我来分解一下。

我需要用WhereSelect语句之类的相同逻辑查询两个不同的集合,而我事先并不知道这个逻辑。假设我有两个集合:

var arrayOne = {"Germane", "Henry", "Charissa", "Evan", "Zorita"};
var arrayTwo = {"Athena", "Darryl", "Zelenia", "Honorato", "Macon"};

还有一些过滤逻辑:

var result = arrayOne.Where(x => x.Length > 3).Select(x => x.Length);

如何在不复制代码本身的情况下将此逻辑复制到第二个数组?有一种方法可以通过委托(delegate)来做到这一点(这是我现在的委托(delegate))

Func<IEnumerable<string>, IEnumerable<int>> query = x => x.Where(x => x.Length > 3).Select(x => x.Length);
var result1 = query(arrayOne);
var result2 = query(arrayTwo );

但我需要逐步构建查询,而不是内联查询,例如

var query = SomeQueryGenerator.CreateQuery();
query.Where(x => x.Length > 3)
if(someCondition)
{
    // Totally random query
    query.Where(x => x.Length % 2 == 0);
} 
var result = query(arrayOne);

这就是问题。现在让我展示我到目前为止所做的事情(并进一步分解我的案例)

当我们试图将大量数据导入我们的数据库时,问题就出现了。这个数据有大约 20k 行,它可能包含一些重复项(我们不想存储),所以检查我们是否已经有特定的行(它通过一些合法的 ID 检查)是非常重要的。我们将 NHibernate 用作 ORM,默认情况下,它会在每个 SELECT 语句之前或任何其他时间经常刷新 INSERTUPDATE

问题是这些刷新需要很长时间,以至于需要长达 10 个小时才能将所有 20k 行加载到数据库中。最明显的方法是将我们当前的 Session.FlushMode 设置为 FlushMode.Never 并在导入结束时刷新它。这样导入 20k 行大约需要 10 分钟。但问题是,当我们查询时,我们看不到重复项,因为它们还不在数据库中,我们的查询如 .Where(x => x.LegalId == someId) 即使实际上已保存的行,也找不到任何东西。我决定利用我们的 Session 一级缓存来完成这项任务,因为我们所有保存的实体都首先写入它的缓存中,然后在 Flush 发生时写入数据库(它可能在我们的 transaction.Commit 之前不会真正写入 DB,但它会通过查询正确地找到这些实体)。 我已经设置了一个可以查询缓存和原始数据库的辅助类,它可以正确地在缓存中找到尚未在数据库中的实体(上面的内联委托(delegate)示例)

但我需要能够逐步查询事物,而我现在完全迷路了。 我们不能只从一个 IQueryable 获取一个 Expression 并将其粘贴到另一个。我们不能创建一些虚拟的 IQueryableIEnumerable 对象并传递它,抛出 .Where.Select因为我们将被绑定(bind)到一个特定的来源,而且我们也不能交换来源(至少我还没有找到一种方法来做到这一点)。

我需要一些关于这个问题的新想法,在此先感谢。

-- 更新数据重复

我们无法预处理我们的数据,让我解释一下原因。

假设我们的文件中有建筑物。一些建筑可以属于一个组织。如果我们遇到一个指定组织的建筑物,我们需要创建它并存储在DB中。这样我们不仅有建筑物(它们本身没有重复),还有它们的组织。几栋建筑完全有可能拥有相同的组织,但我们不需要多次创建这些组织。当然我们可以先解析这个文件,获取所有组织,先导入它们,然后只导入结构,但这太复杂了,而且,正如我在评论中所说,问题更普遍,它不在此导入逻辑的范围

最佳答案

仍然不太确定你到底想做什么,但我想这可以帮助你朝着正确的方向前进:

    var arrayOne = new []{"Germane", "Henry", "Charissa", "Evan", "Zorita"};
    var arrayTwo = new []{"Athena", "Darryl", "Zelenia", "Honorato", "Macon"};

    //var result1 = arrayOne.Where(x => x.Length > 3).Select(x => x.Length);

    bool condition1 = true;
    bool condition2 = false;
    bool condition3 = true;

    var fnc = (Func<IEnumerable, IEnumerable>)(source =>
    {
        var qry = source;
        if (condition1)
        {
            qry = qry.Cast<string>().Where(x => x.Length > 3);
        }

        if (condition2)
        {
            qry = qry.Cast<int>().Where(x => x < 10);
        }

        if (condition3)
        {
            return qry.Cast<string>().Select(x => x.Length);
        }

        return qry;
    });

    var result_v2_1 = fnc(arrayOne);
    var result_v2_2 = fnc(arrayTwo);

请注意,将 consition1 和 condition2 设置为 true 会导致错误。另请注意,condition2 与 String[] 的输入相结合也会导致错误。

关于c# - LINQ查询不同的集合具有相同的逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27635885/

相关文章:

c# - 使用 XDocument 写入 XML,但知道在何处写入

c# - 如何使用 Linq 返回列值已更改的列表或可枚举行

c# - SMTP客户端 : How do I get failed delivery notifications?

c# - VB.NET 开发人员是否不那么好奇? VB.NET 标准化

c# - 为什么 Process.Start 会意外返回 false

c# - 使用 DateTime.Now 插入值时 SqlDateTime 溢出

c# - 如何在本地/内部托管 Azure 辅助角色?

c# - 使用 mvvm 设计模式聚焦 wpf datagrid 单元

c# - 如何合并两个列表的内容?

c# - C#中的字符串格式化