对于使用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查询有什么优势)
- asp.net-mvc – 错误:无法在LINQ to Entities查询中构造实体或复杂类型
- c# – LINQ to SQL查询中的自定义方法
- c# – PLINQ查询中的评估顺序是什么?
- c# – 你可以在内存对象而不是SQL Server查询中使用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查询中构造实体或复杂类型
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; } }
有人可以帮帮我吗?
解决方法
但是,您可以做以下几件事:
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查询中的自定义方法
var result = from u in context.MyTable where MyMethod(u) == 10 select u;
解决方法
您有一个选择是在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查询中的评估顺序是什么?
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将始终为空?
我意识到我正在和鲨鱼游泳,使用这种多线程的力量而不完全了解它的含义.因此问题!谢谢.
解决方法
执行将以.ToList()方法调用开始. Select将仅提供可枚举的IEnumerable列表.
如果某些任务会因异常而失败,您将捕获它们,毕竟您将获得任务列表,其中某些任务将具有“故障”状态.
编辑:
异常抛出将由Task.WaitAll方法调用触发,因此将在之前创建列表,并将精确项目计为初始集合.
更新:
关于Task.WaitAll内部结构:
如果你想知道它是如何工作的,你可以看看source code.
首先是collects all incompleted tasks然后是waits,完成这些任务.
之后它从所有任务中获取collects all inner exceptions,然后将其作为单个AggregateException引发.
c# – 你可以在内存对象而不是SQL Server查询中使用LINQ来提高性能吗?
我一直在考虑将整个对象树加载到内存中并使用LINQ查询对象可能是一种更好的方法.每个对象大多是1-5K
有人有想法吗?
解决方法
今天关于使用LINQ插入/选择-解决查询中的实体构造和使用linq查询有什么优势的介绍到此结束,谢谢您的阅读,有关asp.net-mvc – 错误:无法在LINQ to Entities查询中构造实体或复杂类型、c# – LINQ to SQL查询中的自定义方法、c# – PLINQ查询中的评估顺序是什么?、c# – 你可以在内存对象而不是SQL Server查询中使用LINQ来提高性能吗?等更多相关知识的信息可以在本站进行查询。
本文标签: