Linq To 实体查询

发布于 2024-12-28 16:02:00 字数 952 浏览 2 评论 0原文

考虑以下查询:

var profilelst =
    (
        from i in dbContext.ProspectProfiles
        where i.CreateId == currentUser
        select new ProspectProfile
        {
            ProspectId = i.ProspectId,
            Live = i.Live,
            Name = i.Name,
            ServiceETA = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
                .FirstOrDefault()
                .ServiceETA.ToString(),
            FollowUpDate = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
                .FirstOrDefault()
                .FollowUpDate
        }
    )
    .ToList();

return profilelst.OrderByDescending(c=>c.FollowUpDate)
        .Skip(0).Take(endIndex)
        .ToList();

在此查询中,请查看 FollowUpDateServiceType,这两个都是我从 Opportunity 表中获取的,是否还有其他解决办法来获取这些两者..

表中的一对多关系类似于: ProspectProfile ->机会

我编写的查询是否可以,或者是否有其他可以以更简单的方式完成的解决方案。

Consider the following Query :

var profilelst =
    (
        from i in dbContext.ProspectProfiles
        where i.CreateId == currentUser
        select new ProspectProfile
        {
            ProspectId = i.ProspectId,
            Live = i.Live,
            Name = i.Name,
            ServiceETA = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
                .FirstOrDefault()
                .ServiceETA.ToString(),
            FollowUpDate = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
                .FirstOrDefault()
                .FollowUpDate
        }
    )
    .ToList();

return profilelst.OrderByDescending(c=>c.FollowUpDate)
        .Skip(0).Take(endIndex)
        .ToList();

Here in this query please take a look at FollowUpDate and ServiceType, these both i have fetched from Opportunity table, is there any other work around to get these both..

One to Many Relationship in tables is like: ProspectProfile -> Opportunities

Whether the query i have written is ok or is there any another work around that can be done in easier way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请持续率性 2025-01-04 16:02:00

您可以改进的唯一事情是通过将代码更改为以下内容来避免排序两次:

var profilelst
  = dbContext.ProspectProfiles
             .Where(i => i.CreateId == currentUser)
             .Select(i => 
                    {
                        var opportunity
                           = i.Opportunities
                              .OrderByDescending(t => t.FollowUpDate)
                              .First();
                        return new ProspectProfile
                        {
                            ProspectId = i.ProspectId,
                            Live = i.Live, 
                            Name = i.Name,
                            ServiceETA = opportunity.ServiceETA.ToString(),
                            FollowUpDate = opportunity.FollowUpDate
                        }
                    }).ToList();

return profilelst.OrderByDescending(c => c.FollowUpDate).Take(endIndex).ToList();

我对原始查询进行了一些更改:

  1. 我将其更改为使用方法链语法。在我看来,它更容易阅读。
  2. 我删除了不必要的 Skip(0)
  3. 最大的变化是在 Select 部分:
    1. 我将 FirstOrDefault 更改为 First,因为您无论如何都会访问返回值的属性。如果不存在机会,这将引发描述性异常。这比您所拥有的要好:在您的情况下,它将抛出 NullReferenceException 。这很糟糕,NullReferenceExceptions 总是表明程序中存在错误,而且根本没有描述性。
    2. 我将选择机会的部分移出了初始化器,因此我们只需进行一次排序,而不是两次。

The only thing you can improve is to avoid ordering twice by changing your code to this:

var profilelst
  = dbContext.ProspectProfiles
             .Where(i => i.CreateId == currentUser)
             .Select(i => 
                    {
                        var opportunity
                           = i.Opportunities
                              .OrderByDescending(t => t.FollowUpDate)
                              .First();
                        return new ProspectProfile
                        {
                            ProspectId = i.ProspectId,
                            Live = i.Live, 
                            Name = i.Name,
                            ServiceETA = opportunity.ServiceETA.ToString(),
                            FollowUpDate = opportunity.FollowUpDate
                        }
                    }).ToList();

return profilelst.OrderByDescending(c => c.FollowUpDate).Take(endIndex).ToList();

I made several changes to your original query:

  1. I changed it to use method chains syntax. It is just so much easier to read in my opinion.
  2. I removed the unnecessary Skip(0).
  3. The biggest change is in the Select part:
    1. I changed FirstOrDefault to First, because you are accessing the properties of the return value anyway. This will throw a descriptive exception if no opportunity exists. That's better than what you had: In your case it would throw a NullReferenceException. That's bad, NullReferenceExceptions always indicate a bug in your program and are not descriptive at all.
    2. I moved the part that selects the opportunity out of the initializer, so we need to do the sorting only once instead of twice.
不忘初心 2025-01-04 16:02:00

您的查询中存在不少问题:

  • 您无法投影到实体中(选择新的 ProspectProfile)。 LINQ to Entities 仅支持投影到匿名类型 (select new) 或不属于实体数据模型的其他类型 (select new MySpecialType)

  • LINQ to Entities (ServiceETA.ToString()) 不支持数字或 DateTime 类型的 ToString()

  • FirstOrDefault().ServiceETA (如果 Opportunities 集合为空并且 ServiceETA 是不可为 null 的值类型(例如DateTime),因为 EF 无法将任何值具体化到此类变量中。

  • 在第一个查询后使用 .ToList() 将在数据库中执行查询并加载完整结果。您稍后的 Take 发生在完整列表的内存中,而不是数据库中。 (您可以有效地将整个结果列表从数据库加载到内存中,然后丢弃除第一个之外的所有对象 Takeen。

您可以尝试以下操作:

var profilelst = dbContext.ProspectProfiles
    .Where(p => p.CreateId == currentUser)
    .Select(p => new
    {
        ProspectId = p.ProspectId,
        Live = p.Live,
        Name = p.Name,
        LastOpportunity = p.Opportunities
           .OrderByDescending(o => o.FollowUpDate)
           .Select(o => new
           {
               ServiceETA = o.ServiceETA,
               FollowUpDate = o.FollowUpDate
           })
           .FirstOrDefault()
    })
    .OrderByDescending(x => x.LastOpportunity.FollowUpDate)
    .Skip(startIndex)  // can be removed if startIndex is 0
    .Take(endIndex)
    .ToList();

如果您需要实体 ProspectProfile 的列表,这将为您提供匿名对象的列表。您必须复制此查询后的值。请注意,如果 ProspectProfile 没有 Opportunities,结果中的 LastOpportunity 可能为 null。代码>.

There are quite a few problems in your query:

  • You cannot project into an entity (select new ProspectProfile). LINQ to Entities only supports projections into anonymous types (select new) or other types which are not part of your entity data model (select new MySpecialType)

  • ToString() for a numeric or DateTime type is not supported in LINQ to Entities (ServiceETA.ToString())

  • FirstOrDefault().ServiceETA (or FollowUpdate) will throw an exception if the Opportunities collection is empty and ServiceETA is a non-nullable value type (such as DateTime) because EF cannot materialize any value into such a variable.

  • Using .ToList() after your first query will execute the query in the database and load the full result. Your later Take happens in memory on the full list, not in the database. (You effectively load the whole result list from the database into memory and then throw away all objects except the first you have Takeen.

To resolve all four problems you can try the following:

var profilelst = dbContext.ProspectProfiles
    .Where(p => p.CreateId == currentUser)
    .Select(p => new
    {
        ProspectId = p.ProspectId,
        Live = p.Live,
        Name = p.Name,
        LastOpportunity = p.Opportunities
           .OrderByDescending(o => o.FollowUpDate)
           .Select(o => new
           {
               ServiceETA = o.ServiceETA,
               FollowUpDate = o.FollowUpDate
           })
           .FirstOrDefault()
    })
    .OrderByDescending(x => x.LastOpportunity.FollowUpDate)
    .Skip(startIndex)  // can be removed if startIndex is 0
    .Take(endIndex)
    .ToList();

This will give you a list of anonymous objects. If you need the result in a list of your entity ProspectProfile you must copy the values after this query. Note that LastOpportunity can be null in the result if a ProspectProfile has no Opportunities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文