LINQ 或 Navigation Properties 命令检索 1 到多个数据

如何解决LINQ 或 Navigation Properties 命令检索 1 到多个数据

我正在寻求有关 LINQ SQL 查询的帮助。

我有一个从 Azure SQL 数据库获取数据的 blazor 应用程序。我正在寻求从数据库中获取数据集以链接到数据网格,其中每一行都是主表中的一条记录,与第二个表中的一条记录相连。第二张表有数百万条记录,需要加入一个key(securityId)相同的记录,日期为指定日期的记录,或者指定日期之前的最后一个日期。

由于第二个文件的大小,我需要一个有效的查询。目前我正在使用以下内容,但我相信必须有更有效的方法来做到这一点而没有滞后。也试过导航属性但无法工作

reviewdateS 是我希望第二条记录匹配的日期或该日期之前的最晚日期

            result = (from cmpn in _ctx.MstarCompanies
                      join prcs in _ctx.MstarPrices
                      on cmpn.securityId equals prcs.securityId into cs
                      from c in cs.DefaultIfEmpty()
                      where c.date01 == reviewDateS
                      select new ClsMarketPrices { })

以下是 3 个相关的类。 ClsMarketPrices 与数据库表无关,它是一个简单的类,它结合了其他 2 个类,这可能不是必需的,但据我所知,它是如何工作的。

_ctx 是链接到数据上下文的存储库。

public MySQLRepositories(ApplicationDbContext ctx)
        {
            _ctx = ctx;
        }

 public class ClsMarket
    {
        [Key]
        public int CompanyId { get; set; } = 0;
        public string securityId { get; set; } = "";
        public string companyName { get; set; } = "";
        public string mic { get; set; } = "";
        public string currency { get; set; } = "";
        [ForeignKey("securityId")]
         public virtual ICollection<ClsPrices> Prices { get; set; }    
    }
    public class ClsMarketPrices
    {
        [Key]
        public int CompanyId { get; set; } = 0;    
       public string companyName { get; set; } = "";
        public string period { get; set; } = "";
        public string mic { get; set; } = "";   
    }
 public class ClsPrices
    {        
        [Key]
        public int PricesId { get; set; }
        [ForeignKey("securityId")]
        public string securityId { get; set; } = "";
        public string mic { get; set; } = "";
        public string date01 { get; set; } = "";
        
              
        public virtual ClsMarket ClsMarket {get; set;}

    }

解决方法

我想将第一个文件中的记录与第二个文件中的记录连接起来,其中第二个文件中的记录的日期等于或指定日期之前的最后一个。

所以我们谈论的是文件,而不是数据库!
这很重要,因为这意味着您的本地进程将执行 LINQ,而不是数据库管理系统。换句话说:LINQ 将是 IEnumerable,而不是 IQueryable。

这很重要,因为作为 Enumerable,您将能够定义自己的 LINQ 扩展方法。

虽然你提供了大量不相关的属性,但你忘了给我们最重要的事情:你在谈论两个文件,你告诉我们你有两个具有一对多关系的类,但你给了我们三个班。哪些和你说的有关系?

我认为 ClsMarketPrices 的每个对象都有零个或多个 ClsPrices,并且每个 ClsPrice 都是 ClsMarketPrices 的价格之一,即 {{1 }} 外键 ClsMarketPrices (相当混乱的名称)所指的。

首先,让我们假设您已经有了从文件中读取两个序列的过程。当然,这些过程不会读取超过需要的内容(因此,如果您只使用第一个 SecurityId,请不要读取整个文件)。我假设您已经知道如何做到这一点:

ClsMarket

所以您选择了IEnumerable<ClsMarketPrices> ReadMarketPrices(); IEnumerable<ClsPrices> ReadPrices(); 。每个 DateTime reviewDate 都有零个或多个 MarketPrice。每个 Prices 都有一个 DateTime 属性 Price。对于每个 DateStamp,您希望 MarketPrice 的最大值小于或等于 reviewDate。

如果一个 Price 没有这样的 DateStamp,例如因为它根本没有 MarketPrice,或者它的所有 Prices 都有一个 { {1}} 大于 Price,您需要一个 null 值。

如果一个 MarketPrice 有多个具有相同最大 DateStamp

直接的 LINQ 方法是使用 GroupJoin、Where、Orderby 和 FirstOrDefault:

Prices

问题是:这必须有效地完成,因为您有大量的 DateStampreviewDate

虽然我们已经通过删除 reviewDate 之后的价格来限制要排序的价格数量,但如果您只使用第一个日期,那么订购所有日期仍然是一种浪费。

我们可以通过使用 Aggregate for DateTime reviewDate = ... IEnumerable<ClsMarketPrices> marketPricess = ReadMarketPrices(); IEnumerable<ClsPrices> prices = ReadPrices().Where(price => price.DateStamp <= reviewDate); // GroupJoin marketPrices with prices: var result = markets.GroupJoin(prices,marketPrice => marketPrice.CompanyId,// from every MarketPrice take the primary key price => price.CompanyId,// from every price take the foreign key to its market // parameter resultSelector: from every market,with its zero or more matching prices // make one new: (marketPrice,pricesOfThisMarketPrice) => new { // select the marketPrice properties that you plan to use: Id = marketPrice.CompanyId,Name = ... ... // from all prices of this marketPrice,take the one with the largest DateStamp // we know there are no marketPrices with a DataStamp larger than reviewData LatestPrice = pricesOfThisMarketPrice.OrderbyDescending(price => price.DateStamp) .Select(price => new { // Select the price properties you plan to use; Id = price.PricesId,Date = price.DateStamp,... }) .FirstOrDefault(),}); 来优化它。这将断言 Markets 将仅被枚举一次。

旁注:聚合仅适用于 IEnumerable,不适用于 IQueryable,因此它不适用于数据库。此外,MarketPrices 可能是一个空序列;我们必须解决这个问题。

pricesOfThisMarketPrice

尽管此 Aggregate 比 OrderBy 更有效,但您的第二个序列仍将被枚举不止一次。查看Enumerable.GroupJoin的源代码。

如果你真的想枚举你的第二个源一次,并限制第一个源的枚举次数,可以考虑创建一个扩展方法。这样您就可以将其用作任何 LINQ 方法。如果您不熟悉扩展方法,请参阅 extension methods demystified

您可以为 ClsPrices 和 ClsPrice 创建扩展方法,但是,如果您认为需要更频繁地“查找属于另一个元素的最大元素”,为什么不创建一个泛型方法,就像 LINQ 那样。

下面我创建了最广泛的扩展方法,一个带有 resultSelector 和 equalityComparers。如果您将使用标准等式,请考虑添加一个没有这些比较器的扩展方法,并让该扩展方法调用另一个为比较器提供空值的扩展方法。

有关使用和不使用相等比较器的重载的示例,请参阅多个 LINQ 方法,例如 ToDictionary:有一种方法没有比较器,另一种方法有比较器。第一个调用第二个,比较器的值为空。

我将使用婴儿步骤,以便您了解会发生什么。 这可以稍微优化。 最重要的是,您将只枚举一次最大的集合。

pricesOfThisMarketPrice

实现很简单:

  • 将所有的T1放入字典中,t1Key作为key,{T1,T2}作为value,keyComparer作为比较器

  • 然后仅枚举一次 T2。

    • 检查属性是否
    • 如果是,则在字典中搜索具有相同键的{T1,T2}组合
    • 检查当前 t2Item 是否大于 {T1,T2} 组合中的 T2
    • 如果是:替换

    我们需要一个内部类:

    类字典值 { 公共 T1 T1 {get;放;} 公共 T2 T2 {get;放;} }

代码:

pricesOfThisMarketPrice

t2Sequence的枚举:

LatestPrice = pricesOfThisMarketPrice.Any() ?
    pricesOfThisMarketPrice.Aggregate(

    // select the one with the largest value of DateStamp:
    (latestPrice,nextPrice) => nextPrice.DateStamp >= latesPrice.DateStamp) ? nextPrice : latestPrice)

    // do not do the aggregate if there are no prices at all:
    : null,

因此,对于每个 t1,我们都找到了具有属性

IEnumerable<TResult> TakeLargestItem<T1,T2,TKey,Tproperty,TResult>(
    this IEnumerable<T1> t1Sequence,IEnumerable<T2> t2Sequence,// Select primary and foreign key:
    Func<T1,TKey> t1KeySelector,Func<T2,TKey> t2KeySelector,// Select the property of T2 of which you want the largest element
    Func<T2,TProperty> propertySelector,// The largest element must be <= propertyLimit:
    TProperty propertyLimit,// From T1 and the largest T2 create one TResult
    Func<T1,TResult> resultSelector,// equality comparer to compare equality of primary and foreign key
    IEqualityComparer<TKey> keyComparer,// comparer to find the largest property value
    IComparer<TProperty> propertyComparer)
{
    // TODO: invent a property method name
    // TODO: decide what to do if null input

    // if no comparers provided,use the default comparers:
    if (keyComparer == null) keyComparer = EqualityComparer<TKey>.Default;
    if (propertyComparer == null) propertyComparer = Comparer<TProperty>.Default;

    // TODO: implement
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res