问题描述
我有一个匿名类型的简单的 foreach
循环,我想知道是否有办法使它更有效率。
如果它循环了155项,大约需要20秒才能完成。我省略了它在 boAsset
对象上设置的其他一些属性,但没有什么特别的 - 只是字符串
/ 整数
。
有什么想法吗? 列表与LT; BoAsset> assetList = new List< BoAsset>();
foreach(var结果中的资产)
{
BoAsset boAsset = new BoAsset();
boAsset.Description = asset.Description;
boAsset.DetailedDescription = asset.DetailedDescription;
boAsset.AssetCustomerID = asset.AssetCustomerID;
boAsset.AssetId = asset.AssetId;
boAsset.Keywords = asset.Keywords;
boAsset.Notes = asset.Notes;
boAsset.Photographer = asset.Photographer;
boAsset.PhotographerEmail = asset.PhotographerEmail;
boAsset.Notes = asset.Notes;
boAsset.Author = asset.Author;
boAsset.FileName = asset.FileName;
boAsset.FileExtension = asset.FileExtension;
boAsset.AssetCreateDate = asset.AssetCreateDate;
boAsset.AssetExpireDate = asset.AssetExpireDate;
assetList.Add(boAsset);
var query =(从一个in context.Assets
加入subAf1到context.AssetFiles新的{aid = a.AssetID,ftid = 1}将新的{aid = subAf1.AssetID,ftid = subAf1.AssetTypeID}放入Af1中的Af1
中.Af1.DefaultIfEmpty()
加入subAf2中的context.AssetFiles on {aid = a.AssetID,ftid = 2}将等于new {aid = subAf2.AssetID,ftid = subAf2.AssetTypeID}放入Af2中的Af2
中的Af2.DefaultIfEmpty()
加入subAf3中的context.AssetFiles on {aid = a.AssetID,在新的{aid = a。}中,从Af3.DefaultIfEmpty()
加入subAf4到新的{aid = subAf3.AssetID,ftid = subAf3.AssetTypeID}到Af3
。 AssetID,ftid = 4}将等于new {aid = subAf4.AssetID,ftid = subAf4.AssetTypeID}放入Af4中的Af4
中.Af4.DefaultIfEmpty()
在context.AssetFiles中加入subAf5新的{aid = a.AssetID,ftid = 5}将等于new {aid = subAf5.AssetID,ftid = subAf5.AssetTypeID}放入Af5中的Af5
中的Af5.DefaultIfEmpty()
在上下文中加入subFp。在{fpid = Af1.FilePathID}上的FilePaths等于new {fpid = subFp.FilePathID}从Fp1.DefaultIfEmpty()
中的fp1到Fp1
中//在context中加入fp。Af1.FilePathID上的FilePath等于fp.FilePathID
其中a.AssetCustomerID == custId&& a.AssetID == assetId
选择新{a,Af1,Af2,Af3,Af4,Af5,fp1})。Distinct();
$ b $ var result =从查询中的q
选择新的
{
AssetId = qaAssetID,
AssetCustomerId = qaAssetCustomerID,
StockImage = qaStockImage,
Description = qaDescription,
DetailedDescription = qaDetailedDescription,
Author = qaAuthor,
FileName = q.Af1.FileName,// was 1
FileExtension = q.Af1.FileExtension,//为1
AssetCreateDate = qaAssetCreateDate,
AssetExpireDate = qaAssetExpireDate,
AssetActivateDate = qaAssetActivateDate,
Notes = qa注意,
关键字= qa关键字,
摄影师= qa摄影师,
摄影师电子邮件= qa摄影师电子邮箱
}
我认为您的查询太复杂许多连接),尤其是考虑到有一些甚至没有被使用。注意,一些LINQ提供者(比如LINQ to Entities)可能会花费相当多的时间只要简单地处理一个查询树就可以把它转换成SQL,如果查询很复杂。 (我已经有一些查询需要10或15秒,只是为了分析EF)。
如果我怀疑你正在使用的LINQ实现命中一个数据库,然后使用一个SQL分析工具来检查传递给服务器的实际SQL,以及SQL是如何执行的。
另外,请注意,给定你正在使用的字段,你可以通过物化来消除 foreach
直接返回到 BoAsset
对象。
var result = from查询中的q
选择新的BoAsset
{
AssetId = qaAssetID,
AssetCustomerId = qaAssetCustomerID,
StockImage = qaStockImage,
描述= qaDescription,
DetailedDescription = qaDetailedDescription,
Author = qaAuthor,
FileName = q.Af1.FileName,// was 1
FileExtension = q.Af1.FileExtension,//为1
AssetCreateDate = qaAssetCreateDate,
AssetExpireDate = qaAssetExpireDate,
AssetActivateDate = qaAssetActivateDate,
不es = q.a.Notes,
Keywords = q.a.Keywords,
Photographer = q.a.Photographer,
PhotographerEmail = q.a.PhotographerEmail
};
列表< BoAsset> assetList = result.ToList();
I have this simple foreach
loop of an anonymous type and I'm wondering if there is a way to make it more efficient.
If it loops through 155 items, it takes about 20 seconds to complete. I've omitted some of the other properties it's setting on the boAsset
object, but nothing special - just Strings
/Integers
.
Any thoughts?
List<BoAsset> assetList = new List<BoAsset>();
foreach (var asset in result)
{
BoAsset boAsset = new BoAsset();
boAsset.Description = asset.Description;
boAsset.DetailedDescription = asset.DetailedDescription;
boAsset.AssetCustomerID = asset.AssetCustomerID;
boAsset.AssetId = asset.AssetId;
boAsset.Keywords = asset.Keywords;
boAsset.Notes = asset.Notes;
boAsset.Photographer = asset.Photographer;
boAsset.PhotographerEmail = asset.PhotographerEmail;
boAsset.Notes = asset.Notes;
boAsset.Author = asset.Author;
boAsset.FileName = asset.FileName;
boAsset.FileExtension = asset.FileExtension;
boAsset.AssetCreateDate = asset.AssetCreateDate;
boAsset.AssetExpireDate = asset.AssetExpireDate;
assetList.Add(boAsset);
}
var query = (from a in context.Assets
join subAf1 in context.AssetFiles on new { aid = a.AssetID, ftid = 1 } equals new { aid = subAf1.AssetID, ftid = subAf1.AssetTypeID } into theAf1
from Af1 in theAf1.DefaultIfEmpty()
join subAf2 in context.AssetFiles on new { aid = a.AssetID, ftid = 2 } equals new { aid = subAf2.AssetID, ftid = subAf2.AssetTypeID } into theAf2
from Af2 in theAf2.DefaultIfEmpty()
join subAf3 in context.AssetFiles on new { aid = a.AssetID, ftid = 3 } equals new { aid = subAf3.AssetID, ftid = subAf3.AssetTypeID } into theAf3
from Af3 in theAf3.DefaultIfEmpty()
join subAf4 in context.AssetFiles on new { aid = a.AssetID, ftid = 4 } equals new { aid = subAf4.AssetID, ftid = subAf4.AssetTypeID } into theAf4
from Af4 in theAf4.DefaultIfEmpty()
join subAf5 in context.AssetFiles on new { aid = a.AssetID, ftid = 5 } equals new { aid = subAf5.AssetID, ftid = subAf5.AssetTypeID } into theAf5
from Af5 in theAf5.DefaultIfEmpty()
join subFp in context.FilePaths on new { fpid = Af1.FilePathID } equals new { fpid = subFp.FilePathID } into theFp1
from fp1 in theFp1.DefaultIfEmpty()
//join fp in context.FilePaths on Af1.FilePathID equals fp.FilePathID
where a.AssetCustomerID == custId && a.AssetID == assetId
select new { a, Af1, Af2, Af3, Af4, Af5, fp1 }).Distinct();
var result = from q in query
select new
{
AssetId = q.a.AssetID,
AssetCustomerId = q.a.AssetCustomerID,
StockImage = q.a.StockImage,
Description = q.a.Description,
DetailedDescription = q.a.DetailedDescription,
Author = q.a.Author,
FileName = q.Af1.FileName, //was 1
FileExtension = q.Af1.FileExtension, //was 1
AssetCreateDate = q.a.AssetCreateDate,
AssetExpireDate = q.a.AssetExpireDate,
AssetActivateDate = q.a.AssetActivateDate,
Notes = q.a.Notes,
Keywords = q.a.Keywords,
Photographer = q.a.Photographer,
PhotographerEmail = q.a.PhotographerEmail
}
I think that your query is far too complex (too many joins), especially given that there are a few that are not even used.
Note that some LINQ providers (such as LINQ to Entities) can take quite a bit of time in simply processing a query tree to transform it into SQL, if the query is complex. (I have already had some queries take 10 or 15 seconds just for EF to analyze it.)
If, as I suspect, the LINQ implementation that you are using is hitting a database, then use a SQL profiling tool in order to check what actual SQL is being passed to the server, and how performant that SQL is.
Also, note that given the fields you are using, you could actually do away with the foreach
loop by materializing results directly into the BoAsset
objects.
That is:
var result = from q in query
select new BoAsset
{
AssetId = q.a.AssetID,
AssetCustomerId = q.a.AssetCustomerID,
StockImage = q.a.StockImage,
Description = q.a.Description,
DetailedDescription = q.a.DetailedDescription,
Author = q.a.Author,
FileName = q.Af1.FileName, //was 1
FileExtension = q.Af1.FileExtension, //was 1
AssetCreateDate = q.a.AssetCreateDate,
AssetExpireDate = q.a.AssetExpireDate,
AssetActivateDate = q.a.AssetActivateDate,
Notes = q.a.Notes,
Keywords = q.a.Keywords,
Photographer = q.a.Photographer,
PhotographerEmail = q.a.PhotographerEmail
};
List<BoAsset> assetList = result.ToList();
这篇关于C#匿名类型的foreach循环,更好的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!