Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何优化LINQ DB请求?_C#_Linq - Fatal编程技术网

C# 如何优化LINQ DB请求?

C# 如何优化LINQ DB请求?,c#,linq,C#,Linq,我有下一个代码,取DB中元素的最后一个和前最后一个参数: var result = _context.Contacts.Where(conts => conts.CreatorUserId == _userManager.GetUserId(this.User)) .Select(conts => new { conts.ID, conts.Mobile, conts.Email, cont

我有下一个代码,取DB中元素的最后一个和前最后一个参数:

var result =  _context.Contacts.Where(conts => conts.CreatorUserId == _userManager.GetUserId(this.User))
     .Select(conts => new
     {
         conts.ID,
         conts.Mobile,
         conts.Email,
         conts.Facebook,
         conts.StateId,
         conts.CreatorUserId,
         conts.Birthday,
         conts.Description,
         conts.Name,
         conts.Photo,
         conts.SecondName,

         Tags = conts.Tags.Select(d=> d.UserTag.Emoji),
         NpaId = conts.NpaInfo.NpaId,

         PartnerPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.MyPV).FirstOrDefault(),
         GroupPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.GroupPV).FirstOrDefault(),
         LevelPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault(),


         PartnerPv = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(1).Select(x => x.MyPV).FirstOrDefault(),
         Level = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault(),// conts.NpaInfo.PerformanceBonusLevelId,
         GroupPv = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(1).Select(x => x.GroupPV).FirstOrDefault(),

         EntryDate = conts.NpaInfo.EntryDate,
         ExpirationDate = conts.NpaInfo.ExpirationDate
     });
事实上,该部分:

PartnerPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.MyPV).FirstOrDefault(),
GroupPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.GroupPV).FirstOrDefault(),
LevelPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault()
在1个请求中转换为类似的内容(仅显示一个块的部分):

我不想重复同一部分多次:

conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1)
所以,如果我喜欢这个:

PrevBuffer = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(                               
     param => new
     {

         param.MyPV,
         param.GroupPV,
         param.PerformanceBonusLevelId
     }
     ),
它将在输出中为每行显示许多单独的请求,如:

SELECT [x0].[MyPV], [x0].[GroupPV], [x0].[PerformanceBonusLevelId]
FROM [NpaDatas] AS [x0]
WHERE @_outer_ID1 = [x0].[NpaInfoId]
ORDER BY [x0].[DataMonth] DESC
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
这一部分也是如此:

Tags = conts.Tags.Select(d=> d.UserTag.Emoji)
将获得多个选择,如:

SELECT [d.UserTag].[Emoji]
FROM [ContactTags] AS [d]
LEFT JOIN [UserTags] AS [d.UserTag] ON [d].[UserTagId] = [d.UserTag].[ID]
WHERE @_outer_ID = [d].[ContactId]

是否可以对其进行优化?

您应该使用GroupBy:

    class Program
    {
        static void Main(string[] args)
        {
            Conts conts = new Conts();

            List<NpaDatas> data = conts.NpaInfo.NpaDatas
                .OrderByDescending(x => x.DataMonth)
                .GroupBy(x => x.DataMonth).Select(x => x.FirstOrDefault()).ToList();

            //To get the second latest use followng
            NPaDatas results = data.Skip(1).FirstOrDefault();
        }
    }

    public class NpaDatas
    {
        public string NpaInfoId { get; set; }
        public DateTime DataMonth { get; set; }
        public PV PartnerPv { get; set; }
        public PV PerformanceBonusLevelId { get; set; }
        public PV GroupPv { get; set; }
    }
    public class PV
    {
        //data not specified 
    }
    public class Conts
    {
        public NpaInfo NpaInfo { get; set; }
    }
    public class NpaInfo
    {
        public string ID { get; set; }
        public List<NpaDatas> NpaDatas { get; set; }
    }
类程序
{
静态void Main(字符串[]参数)
{
Conts Conts=新Conts();
列表数据=conts.NpaInfo.npadass
.OrderByDescending(x=>x.DataMonth)
.GroupBy(x=>x.DataMonth)。选择(x=>x.FirstOrDefault()).ToList();
//获取以下第二个最新用法
NPADASS结果=data.Skip(1).FirstOrDefault();
}
}
公共类数据
{
公共字符串NpaInfoId{get;set;}
公共日期时间数据月{get;set;}
公共PV PartnerPv{get;set;}
公共PV PerformanceBonusLevelId{get;set;}
公共PV组PV{get;set;}
}
公共级光伏
{
//未指定数据
}
公共类Conts
{
公共NpaInfo NpaInfo{get;set;}
}
公共类NpaInfo
{
公共字符串ID{get;set;}
公共列表数据集{get;set;}
}

这样做将显著改进查询

var result = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(2).ToArray();

PartnerPvPrev = result.Skip(1).Take(1).Select(x => x.MyPV).FirstOrDefault();
  GroupPvPrev = result.Skip(1).Take(1).Select(x => x.GroupPV).FirstOrDefault();
    LevelPrev = result.Skip(1).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault();
    PartnerPv = result.Take(1).Select(x => x.MyPV).FirstOrDefault();
        Level = result.Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault();
      GroupPv = result.Take(1).Select(x => x.GroupPV).FirstOrDefault();

您应该首先选择重复零件,并在后续查询中使用这些零件。使用
let
关键字,这在查询语法中要容易得多:

var result = from conts in _context.Contacts
    where conts.CreatorUserId == _userManager.GetUserId(this.User)
    let monthsSorted = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth)
    let firstMonth = monthsSorted.FirstOrDefault()
    let prevMonth = monthsSorted.Skip(1).FirstOrDefault()
    select new
    {
        conts.ID,
        conts.Mobile,
        conts.Email,
        conts.Facebook,
        conts.StateId,
        conts.CreatorUserId,
        conts.Birthday,
        conts.Description,
        conts.Name,
        conts.Photo,
        conts.SecondName,

        Tags = conts.Tags.Select(d=> d.UserTag.Emoji),
        NpaId = conts.NpaInfo.NpaId,

        PartnerPvPrev = prevMonth.MyPV,
        GroupPvPrev = prevMonth.GroupPV,
        LevelPrev = prevMonth.PerformanceBonusLevelId,

        PartnerPv = firstMonth.MyPV,
        GroupPv = firstMonth.GroupPV,
        Level = firstMonth.PerformanceBonusLevelId,

        EntryDate = conts.NpaInfo.EntryDate,
        ExpirationDate = conts.NpaInfo.ExpirationDate
    };

而不是两个查询<代码>跳过(1)。执行(1),然后稍后执行
Take(1)
您可以尝试组合到
Take(2)
的单个查询,然后执行逻辑客户端(可能存在一个
Take(2)
解决方案,这都是数据库端,我不知道)。。。这将使您的查询总数减少一半,至少您真的应该显示一个。您粘贴的代码似乎是
new
匿名对象创建的一部分。所有的数据库工作都是在此之外进行的,这将是我们优化查询所需要看到的。更新了完整版本的代码。但是ToArray()将获取NpaData的所有字段,我只需要其中6个字段(Last的3个和Prev的3个)。在您的情况下,如果我可以像:result[0]这样索引值,为什么还要在这里再次选择。MyPv@user2377299-然后选择
.ToArray()
之前的三个字段。为了简单起见,我保留了原始代码。@Enigmativity您能解释一下它如何比所讨论的解决方案本身更好吗?
.ToArray()
强制执行查询,以便只向数据库发送一个查询。接下来的6行都是从内存中的数据开始工作的。对不起,可能有一些误解。NpaInfo有多个NpaData。每个NpaData都有级别、PartnerPv、GrouPv。我需要取最后和最后之前的物品。NpaData不包含这6个字段。我根据您发布的SQL更新了代码,但您的SQL看起来不正确。我不明白你为什么需要筛选ID。我怀疑你应该有一个列表,每个列表都应该只有相同的ID。此外,发布的SQL有额外的右括号,这意味着你没有发布整个SQL。联系人有一个NpaInfo。NpaInfo有许多日期不同的NpaData。我需要从当前用户创建的联系人的NpaInfo的每个NpaData(上一个和上一个)中提取3个参数。SQL-只对重复的问题部分进行了短路。因此,您与我确认NpaInfo和NAPDATA的ID将相同,因此您不需要筛选ID?我的查询有什么问题吗?NpaInfo.ID!=NapData.ID-两个不同的对象。我在哪里按ID过滤?这6个值中的每一个都有多个选择。比如:从[NpaDatas]中选择[x].[MyPV]作为[x],其中[conts.NpaInfo].[ID]=[x].[NpaInfoId]按[x].[DataMonth]排序。[DataMonth]DESC OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLYOK,显然这是LINQ to SQL(请始终使用特定的标记)。在实体框架中,这将产生重大影响。恐怕您唯一的选择是不在一个查询中收集所有数据,因为LINQ to SQL在执行此操作时总是效率低下。我已经对此进行了再次研究,实际上,这是您唯一的选择--或者您最初的查询,但至少我的查询更易于阅读。使用LINQ to SQL,您将始终根据希望在结果中包含的
conts.NpaInfo.NpaData
属性获得子查询。我已经研究了获取2个
conts.NpaInfo.NpaData
项的集合(
Take(2)
)并在以后将结果展平的替代方法,但这总是会产生N+1个查询。如果当前查询的执行情况合理,请继续执行,否则请找到另一种方法来收集数据。
var result = from conts in _context.Contacts
    where conts.CreatorUserId == _userManager.GetUserId(this.User)
    let monthsSorted = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth)
    let firstMonth = monthsSorted.FirstOrDefault()
    let prevMonth = monthsSorted.Skip(1).FirstOrDefault()
    select new
    {
        conts.ID,
        conts.Mobile,
        conts.Email,
        conts.Facebook,
        conts.StateId,
        conts.CreatorUserId,
        conts.Birthday,
        conts.Description,
        conts.Name,
        conts.Photo,
        conts.SecondName,

        Tags = conts.Tags.Select(d=> d.UserTag.Emoji),
        NpaId = conts.NpaInfo.NpaId,

        PartnerPvPrev = prevMonth.MyPV,
        GroupPvPrev = prevMonth.GroupPV,
        LevelPrev = prevMonth.PerformanceBonusLevelId,

        PartnerPv = firstMonth.MyPV,
        GroupPv = firstMonth.GroupPV,
        Level = firstMonth.PerformanceBonusLevelId,

        EntryDate = conts.NpaInfo.EntryDate,
        ExpirationDate = conts.NpaInfo.ExpirationDate
    };