[英]Increase EF query performance
I currently have the following code in my project 我的项目中目前有以下代码
public List<PermissionValue> GetUnderlyingPermissionsForUser(string userName, int guiPermissionTypeId, int productTypeId)
{
using (CliVeEntities db = new CliVeEntities())
{
var listUnderlyings = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& gui.UnderlyingId.HasValue
&& !gui.SectorId.HasValue
&& gui.ProductTypeId == null
&& gui.ProductGroupId == null
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value}).ToList<PermissionValue>();
var listUnderlyingsProductGroup = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
join pg in db.ProductGroup on gui.ProductGroupId equals pg.ProductGroupId
join pt in db.ProductType on pg.ProductGroupId equals pt.ProductGroupId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& gui.UnderlyingId.HasValue
&& !gui.SectorId.HasValue
&& pt.ProductTypeId == productTypeId
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsProductType = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& gui.UnderlyingId.HasValue
&& !gui.SectorId.HasValue
&& gui.ProductTypeId == productTypeId
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsForSectors = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
join u in db.Underlying on gui.SectorId equals u.SectorId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& !gui.UnderlyingId.HasValue
&& gui.ProductTypeId == null
&& gui.ProductGroupId == null
select new PermissionValue { Id = u.UnderlyingId, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsForSectorsProductGroup = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
join u in db.Underlying on gui.SectorId equals u.SectorId
join pg in db.ProductGroup on gui.ProductGroupId equals pg.ProductGroupId
join pt in db.ProductType on pg.ProductGroupId equals pt.ProductGroupId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& !gui.UnderlyingId.HasValue
&& pt.ProductTypeId == productTypeId
select new PermissionValue { Id = u.UnderlyingId, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsForSectorsProductType = (
from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& !gui.UnderlyingId.HasValue
&& gui.SectorId.HasValue
&& gui.ProductTypeId == productTypeId
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value }).ToList<PermissionValue>();
var mergeList1 = MergeAndDistinctList(listUnderlyings, listUnderlyingsProductType);
var mergeList2 = MergeAndDistinctList(mergeList1, listUnderlyingsProductGroup);
var mergeList3 = MergeAndDistinctList(mergeList2, listUnderlyingsForSectors);
var mergeList4 = MergeAndDistinctList(mergeList3, listUnderlyingsForSectorsProductType);
var resultMergeList = MergeAndDistinctList(mergeList4, listUnderlyingsForSectorsProductGroup);
return resultMergeList;
And This is the code for my MergeAndDistinctList function 这是我的MergeAndDistinctList函数的代码
protected List<PermissionValue> MergeAndDistinctList(List<PermissionValue> listPrimary, List<PermissionValue> listSecondry)
{
List<PermissionValue> listMergedAndDistinct = new List<PermissionValue>();
listMergedAndDistinct.AddRange(listPrimary);
var filter = listPrimary.Select<PermissionValue, int>(p => p.Id);
listMergedAndDistinct.AddRange(listSecondry.Where<PermissionValue>(p => !filter.Contains(p.Id)).Select(p => p));
return listMergedAndDistinct;
}
My problem with my GetUnderlyingsForClient() code is that it hits the database multiple times. 我的GetUnderlyingsForClient()代码的问题是它多次击中数据库。 If this method gets hit quite a lot then this could translate to multiple calls to the database.
如果此方法受到很大的打击,那么这可能会转换为对数据库的多次调用。
Does anybody know of any ways to make this code more efficient and reduce the amount of DB calls i have to make. 是否有人知道有什么方法可以使此代码更高效并减少我必须进行的数据库调用量。
It seems that you make a lot of queries on the same table (a in your case) 似乎您在同一张表上进行了很多查询(在您的情况下为a)
To limit database queries, you can get all data needed in a local list and use this list for your multiple queries like this : 为了限制数据库查询,您可以在本地列表中获取所需的所有数据,并将此列表用于多个查询,如下所示:
var MyBaseList = db.A.ToList();
var listUnderlyings = (from a MyBaseList [...]
var listUnderlyingsProductGroup = (from a MyBaseList [...]
And for limit the data retrieval, filter MyBaseList to get only lines used by following queries. 为了限制数据检索,请过滤MyBaseList以仅获取以下查询使用的行。
You could Union
your queries following this simplified pattern: 你可以
Union
你的查询下面这个简单的模式:
(from a in As where a.Id > 0 select a)
.Union(
from a in As where a.Name == "a" select a)
.Union(
...
)
.Select(a => new { a.x, a.y })
.Distinct()
The Union
is the merge part of your MergeAndDistinctList and the Distinct
, ehh, the distinct part. Union
是您的MergeAndDistinctList和Distinct
的合并部分,是不同的部分。 The nice thing is: the Distinct is carried out over the projection (Id and Visible in your case). 妙处是:在投影上进行了区分(在您的情况下为ID和Visible)。
Everything should be carried out in one (monster) query now, without the intermediate forced execution that is caused by the AddRange
in MergeAndDistinctList. 现在,所有操作都应在一个(
AddRange
)查询中执行,而没有由MergeAndDistinctList中的AddRange
引起的中间强制执行。
Looking at your queries I have a feeling that you could do with a smaller number of them by combining some conditions, but that's up to you. 查看您的查询,我觉得您可以通过组合一些条件来处理较少的查询,但这取决于您。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.