GVKun编程网logo

使用LINQ插入/选择-解决查询中的实体构造(使用linq查询有什么优势)

6

对于使用LINQ插入/选择-解决查询中的实体构造感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍使用linq查询有什么优势,并为您提供关于asp.net-mvc–错误:无法在LINQtoEnti

对于使用LINQ插入/选择-解决查询中的实体构造感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍使用linq查询有什么优势,并为您提供关于asp.net-mvc – 错误:无法在LINQ to Entities查询中构造实体或复杂类型、c# – LINQ to SQL查询中的自定义方法、c# – PLINQ查询中的评估顺序是什么?、c# – 你可以在内存对象而不是SQL Server查询中使用LINQ来提高性能吗?的有用信息。

本文目录一览:

使用LINQ插入/选择-解决查询中的实体构造(使用linq查询有什么优势)

使用LINQ插入/选择-解决查询中的实体构造(使用linq查询有什么优势)

我在代码中使用了DBML自动生成的LINQ to
SQL类,因此能够适当地选择和插入数据将是很棒的。这是另一篇文章中建议的一种方法。在下面的示例中,e_activeSession是DataContext中表的自动生成的表示形式:

var statistics =    from record in startTimes    group record by record.startTime into g    select new e_activeSession            {                workerId = wcopy,                startTime = g.Key.GetValueOrDefault(),                totalTasks = g.Count(),                totalTime = g.Max(o => o.record.timeInSession).GetValueOrDefault(),                minDwell = g.Min(o => o.record.dwellTime).GetValueOrDefault(),                maxDwell = g.Max(o => o.record.dwellTime).GetValueOrDefault(),                avgDwell = g.Average(o => o.record.dwellTime).GetValueOrDefault(),                stdevDwell = g.Select(o => Convert.ToDouble(o.record.dwellTime)).StdDev(),                total80 = g.Sum(o => Convert.ToInt16(o.record.correct80) + Convert.ToInt16(o.record.wrong80)),                correct80 = g.Sum(o => Convert.ToInt16(o.record.correct80)),                percent80 = Convert.ToDouble(g.Sum(o => Convert.ToInt16(o.record.correct80))) /                            g.Sum(o => Convert.ToInt16(o.record.correct80) + Convert.ToInt16(o.record.wrong80))            };

上面引发了错误,所以我尝试了以下方法:

var groups =    from record in startTimes    group record by record.startTime    into g    select g;var statistics = groups.ToList().Select(    g => new e_activeSession             {                 workerId = wcopy,                 startTime = g.Key.GetValueOrDefault(),                 totalTasks = g.Count(),                 totalTime = g.Max(o => o.record.timeInSession).GetValueOrDefault(),                 minDwell = g.Min(o => o.record.dwellTime).GetValueOrDefault(),                 maxDwell = g.Max(o => o.record.dwellTime).GetValueOrDefault(),                 avgDwell = g.Average(o => o.record.dwellTime).GetValueOrDefault(),                 stdevDwell = g.Select(o => Convert.ToDouble(o.record.dwellTime)).StdDev(),                 total80 = g.Sum(o => Convert.ToInt16(o.record.correct80) + Convert.ToInt16(o.record.wrong80)),                 correct80 = g.Sum(o => Convert.ToInt16(o.record.correct80)),                 percent80 = Convert.ToDouble(g.Sum(o => Convert.ToInt16(o.record.correct80))) /                             g.Sum(o => Convert.ToInt16(o.record.correct80) + Convert.ToInt16(o.record.wrong80))             });

但是,这种方法ToList似乎效率极低,只会使我的代码坐在那里很长时间。有一个更好的方法吗?

答案1

小编典典

AsEnumerable()``ToList()在将处理引入linq-to-
object方面将做相同的事情,但是不会浪费时间和内存先存储所有这些对象。相反,当您遍历它时,它将一次创建一个对象。

通常,应该使用AsEnumerable()将操作从另一个源移动到内存中的方法,而不是ToList()除非您确实想要一个列表(例如,如果您要多次击打相同的数据,那么该列表将用作缓存)。

到目前为止,我们有:

var statistics = (  from record in startTimes  group record by record.startTime  into g  select g;  ).AsEnumerable().Select(    g => new e_activeSession    {      workerId = wcopy,      startTime = g.Key.GetValueOrDefault(),      totalTasks = g.Count(),      totalTime = g.Max(o => o.record.timeInSession).GetValueOrDefault(),      /* ... */     });

但是还有一个更大的问题。您也要小心groupby。与聚合方法一起使用时,通常是可以的,但否则最终可能会变成许多数据库调用(一次获取键的不同值,然后每个值一次)。

考虑到以上内容(我省略了不提及每一列的内容)。如果不使用AsEnumerable()(或不使用ToList()您所拥有的),由于wcopy大概完全不在查询范围内(我看不到它的定义位置),则第一个生成的SQL将是(如果允许的话),类似于:

select startTime, count(id), max(timeInSession), /* ... */from tasksgroup by startTime

数据库应该对它进行相当有效的处理(如果不是,请检查索引并在生成的查询上运行数据库引擎优化顾问)。

但是,在内存中进行分组时,它很可能会首先执行:

select distinct startTime from tasks

接着

select timeInSession, /* ... */from taskswhere startTime = @p0

对于startTime找到的每一个不同点,将其作为传递@p0。无论其余代码的效率如何,这都会很快造成灾难性的后果。

我们有两个选择。哪一个最佳视情况而异,所以我将两者都给出,尽管第二个在这里是最有效的。

有时,我们最好的方法是加载所有相关行并在内存中进行分组:

var statistics =  from record in startTimes.AsEnumerable()  group record by record.startTime  into g  select new e_activeSession  {    workerId = wcopy,    startTime = g.Key.GetValueOrDefault(),    totalTasks = g.Count(),    totalTime = g.Max(o => o.record.timeInSession).GetValueOrDefault(),    /* ... */  };

通过仅选择我们关心的列,我们也许可以使其效率更高一点(如果以上内容仍然使用了表中的每一列,则无关紧要)

var statistics =  from record in (    from dbRec in startTimes    select new {dbRec.startTime, dbRec.timeInSession, /*...*/}).AsEnumerable()    group record by record.startTime    into g    select new e_activeSession    {      workerId = wcopy,      startTime = g.Key.GetValueOrDefault(),      totalTasks = g.Count(),      totalTime = g.Max(o => o.record.timeInSession).GetValueOrDefault(),      /* ... */    };

我认为这不是最好的情况。在要枚举组,然后枚举每个组的情况下,我会用到它。如果您要对每个组进行汇总,而不要对它们进行枚举,则最好将该汇总工作保留在数据库中。数据库擅长于此,它将大大减少通过网络发送的数据总量。在这种情况下,我能想到的最好的办法是强制使用一个新对象,而不是镜像它的实体类型,但该对象不能被识别为实体。您可以为此创建一个类型(如果您要对此进行多个变体,则很有用),否则可以使用匿名类型:

var statistics = (  from record in startTimes  group record by record.startTime  into g  select new{    startTime = g.Key.GetValueOrDefault(),    totalTasks = g.Count(),    totalTime = g.Max(o => o.record.timeInSession).GetValueOrDefault(),    /* ... */  }).AsEnumerable().Select(    d => new e_activeSession    {      workerId = wcopy,      startTime = d.startTime,      totalTasks = d.totalTasks,      /* ... */    });

显而易见的缺点是冗长的冗长。但是,它将使操作在db中保持最佳状态,同时又不浪费时间和内存ToList(),不会像e_activeSession往常那样反复击中db,并将创建的内容从linq2sql拖入linq2objects中,因此应该允许这样做。

(顺便说一句,.NET中的约定是类和成员名以大写字母开头。这没有技术原因,但是这样做意味着您将匹配更多人的代码,包括BCL和您使用的其他库的代码)。

编辑:顺便说一句;我刚刚看到了您的其他问题。请注意,在某种程度上,AsEnumerable()这里是导致该问题的确切原因的变体。搞清楚了,您将对不同的linq查询提供程序之间的界限感到很困惑。

asp.net-mvc – 错误:无法在LINQ to Entities查询中构造实体或复杂类型

asp.net-mvc – 错误:无法在LINQ to Entities查询中构造实体或复杂类型

我有一个与MVC连接查询的问题,我不知道为什么.

The entity or complex type ‘Tusofona_Website.Models.site_noticias’ cannot be constructed in a LINQ to Entities query.

我的控制器:

private TusofonaDBs db = new TusofonaDBs();

    //
    // GET: /DestaquesMain/

    public ActionResult Index()
    {
        var query = (from sd in db.site_desquesnoticias
                    join sn in db.site_noticias on sd.IDNoticia equals sn.IDNoticia
                    where sn.Destaque == 1
                    select new site_noticias {
                        CorpoNoticia = sn.CorpoNoticia,TituloNoticia = sn.TituloNoticia
                    }).ToList();

        //return View(db.site_desquesnoticias.ToList());
          return View(query);

    }

我的型号:

public class site_destaquesnoticias
{
    [Key]
    public Int32 IDDestaque { get; set; }
    public Int32 IDNoticia { get; set; }
    public string Foto { get; set; }


}

public class site_noticias
{
    [Key]
    public Int32 IDNoticia { get; set; }
    public string CorpoNoticia { get; set; }
    public string TituloNoticia { get; set; }
    public string Foto { get; set; }
    public Int32 Destaque { get; set; }
}

public class TusofonaDBs : DbContext
{
    public DbSet<site_destaquesnoticias> site_desquesnoticias { get; set; }
    public DbSet<site_noticias> site_noticias { get; set; }
}

有人可以帮帮我吗?

解决方法

您无法投影到映射的实体(请参阅 this答案).

但是,您可以做以下几件事:

1)选择匿名类型而不是实体,如:

var query = (from sd in db.site_desquesnoticias
                    join sn in db.site_noticias on sd.IDNoticia equals sn.IDNoticia
                    where sn.Destaque == 1
                    select new {
                        CorpoNoticia = sn.CorpoNoticia,TituloNoticia = sn.TituloNoticia
                    }).ToList();

2)反转您的查询以直接选择site_noticias.这取决于您要检索的查询和数据.例如,您可以查看以下内容是否有效并为您提供所需的数据:

var query = (from sd in db.site_desquesnoticias
                    join sn in db.site_noticias on sd.IDNoticia equals sn.IDNoticia
                    where sn.Destaque == 1
                    select sn).ToList();

3)使用一些DTO(数据传输对象)将要选择的属性投影到:

public class SiteNoticiasDTO{
     public string CorpoNoticia {get;set;}
     public string TituloNoticia {get;set;}
    }

var query = (from sd in db.site_desquesnoticias
                    join sn in db.site_noticias on sd.IDNoticia equals sn.IDNoticia
                    where sn.Destaque == 1
                    select new SiteNoticiasDTO {
                        CorpoNoticia = sn.CorpoNoticia,TituloNoticia = sn.TituloNoticia
                    }).ToList();

c# – LINQ to SQL查询中的自定义方法

c# – LINQ to SQL查询中的自定义方法

是否可以使用自定义方法在查询中例如:

var result = from u in context.MyTable where MyMethod(u) == 10 select u;

解决方法

正如Pranay所解释的那样,您不能将自定义(C#)方法作为LINQ to SQL查询的一部分,因为LINQ to sql无法查看方法的表达式树,因此无法将其转换为sql.

您有一个选择是在sql中编写函数并将其作为sql函数存储在sql Server上(可能,您也可以使用sql CLR,但我还没有尝试过).然后,您可以将该函数添加到DataContext类型,LINQ to sql将其转换为对sql Server上的函数的调用.就像是:

var result = from u in context.MyTable 
             where context.MyMethod(u) == 10 select u;

当然,问题是你需要在sql中编写函数(我认为sql CLR也可以工作 – 不确定性能和其他可能的复杂性)

我也是wrote an article(前一段时间),当你将“方法”作为表达式树方式(作为Expression< Func< ...>>>类型的值)编写时,它显示了如何执行此操作,这是可能的,因为在这种情况下,代码被编译为表达式树.但是,必须完成一些后处理,您仍然可以只编写一个可以在LINQ查询中轻松内联的表达式.

c# – PLINQ查询中的评估顺序是什么?

c# – PLINQ查询中的评估顺序是什么?

下面是我在 Windows服务中定期运行的PLINQ查询示例:

var resultList = new List<Task<SendMailResult>>();

try
{
    resultList = emailsToSend
        .AsParallel().WithDegreeOfParallelism(10)
        .Select(async e =>
        {
            bool bSuccess = false;

            if (await MailHelper.SendMailAsync(e.sTo,e.sSubject,e.sHTML) == true)
            {
                bSuccess = true;
            }

            return new SendMailResult
            {
                succeeded = bSuccess,resultid = e.id
            };
        }).ToList();

    Task.WaitAll(resultList.ToArray());
}
catch (AggregateException aggEx)
{
    foreach (var ex in aggEx.InnerExceptions)
        Console.Out.WriteLine(ex.Message);
}

我的问题是 – 如果在内部匿名异步Func< EmailToSend,Task< SendMailResult>>中抛出异常. (虽然很可能调用MailHelper.SendMailAsync()),然后调用AggregateException处理程序 – 是否会在任何时候调用以下.ToList()?

换句话说,是否有可能某些任务成功完成,直到一个没有完成,并且在被捕获到AggregateException处理程序之后跟随下面的代码片段,我可能有一个非0计数的resultList?或者一个异常意味着永远不会调用ToList(),如果抛出异常,resultList将始终为空?

我意识到我正在和鲨鱼游泳,使用这种多线程的力量而不完全了解它的含义.因此问题!谢谢.

解决方法

由于Select laziness,任何时候都会调用.ToList(),结果列表将包含所有任务.
执行将以.ToList()方法调用开始. Select将仅提供可枚举的IEnumerable列表.
如果某些任务会因异常而失败,您将捕获它们,毕竟您将获得任务列表,其中某些任务将具有“故障”状态.

编辑:
异常抛出将由Task.WaitAll方法调用触发,因此将在之前创建列表,并将精确项目计为初始集合.

更新:
关于Task.WaitAll内部结构:
如果你想知道它是如何工作的,你可以看看source code.
首先是collects all incompleted tasks然后是waits,完成这些任务.
之后它从所有任务中获取collects all inner exceptions,然后将其作为单个AggregateException引发.

c# – 你可以在内存对象而不是SQL Server查询中使用LINQ来提高性能吗?

c# – 你可以在内存对象而不是SQL Server查询中使用LINQ来提高性能吗?

我们一直在开发一个数据库Web应用程序,该应用程序不断查询sql存储中的对象(大约80,000个),这些对象在层次结构中彼此相关. (即许多物体具有与同一表中的另一个物体相关的parentid)

我一直在考虑将整个对象树加载到内存中并使用LINQ查询对象可能是一种更好的方法.每个对象大多是1-5K

有人有想法吗?

解决方法

“LINQ”包括LINQ to Objects,LINQ to sql等.您当然可以在内存中查询,但也许您应该等到优化之前完成性能分析.你可以优化错误的东西.

今天关于使用LINQ插入/选择-解决查询中的实体构造使用linq查询有什么优势的介绍到此结束,谢谢您的阅读,有关asp.net-mvc – 错误:无法在LINQ to Entities查询中构造实体或复杂类型、c# – LINQ to SQL查询中的自定义方法、c# – PLINQ查询中的评估顺序是什么?、c# – 你可以在内存对象而不是SQL Server查询中使用LINQ来提高性能吗?等更多相关知识的信息可以在本站进行查询。

本文标签: