微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 OUTER APPLY 用于 SqlQuery<T>,其中 T 具有 IEnumerable 属性

如何解决将 OUTER APPLY 用于 SqlQuery<T>,其中 T 具有 IEnumerable 属性

由于使用 Linq 的性能问题,我正在使用字符串 sql 查询。由于很多outer apply,而且很多where子句使用IN。为清楚起见,此示例中的代码在此处进行了缩减。我省略了向 where 子句添加(或不添加)大量代码的 IF-ELSE 语句。

这是我的业务对象,它有一个 IEnumerable 作为属性

public class AssetBO
{
    public Guid AssetId { get; set; }
    public Guid SiteId { get; set; }
    public string Name { get; set; }
    public IEnumerable<AssetDivisionBO> AssetDivisionInfo { get; set; }
}

这是我的字符串 sql

string sql_Data = @"SELECT disTINCT e.AssetId,e.SiteId,e.Name 
    FROM
        Asset.vAssetLinkBox e 

            OUTER APPLY (
              SELECT  
                ld.AssetDivisionId,ld.SiteId,ld.AssetId,ld.DivisionId,ld.IsDeleted,ld.Created,ld.LastModified,ld.ModifiedByEmployeeId,ld.CreatedByEmployeeId,FROM  Asset.AssetDivision ld
              WHERE
                    ld.IsDeleted = 0
                    AND ld.AssetId = e.AssetId
           ) AS AssetDivisionInfo   
WHERE
    e.IsDeleted = 0";

然后我运行这个:

var query = context.Database.sqlQuery<AssetBO>(sql_Data);

List<AssetBO> assets = query.ToList<AssetBO>();

我想从字符串 sql 中的 OUTER APPLY 填充 IEnumerable AssetDivisionInfo。这可能吗?

我得到了我的 AssetBO 对象,而 AssetDivisionInfo 为空。有没有办法映射它?

编辑:我被要求提供原始的 Linq,所以现在将其发布在这里。我需要所有这些 OUTER APPLIES 与数据一起返回。

public static List<ModuleView.AssetBO> Asset_GetList_ByRadFilter(COG_ContextDB context,RadFilter filter,string where_clause,Guid Base_ContextSiteId,Guid Base_ContextEmployeeId,HashSet<Guid> PassedAssetIdList,bool Base_ContextEmployee_IsForAllDivisions,int PageNumber,int PageSize,string OrderByField,bool IsDescending,bool IsRestrictedByDivision,HashSet<Guid?> Employee_DivisionIdList,out int RecordCount)
{
    var interceptor = new Common.BLL.CommandInterceptorHelper();
    System.Data.Entity.Infrastructure.Interception.DbInterception.Add(interceptor);

    HashSet<Guid> IsForAll_AssetIdList = new HashSet<Guid>();

    if (IsRestrictedByDivision == true)
    {
        //db hit,so calling only if IsRestrictedByDivision == true
        IsForAll_AssetIdList = GetIsForAllDivisions_Assets(context,Base_ContextSiteId);
    }
    else
    {
        Base_ContextEmployee_IsForAllDivisions = false;
    }

    var query = from e in context.vAssetLinkBoxes
                from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()

                    //OUTER APPLY to get a list of AssetIds from AssetDivision table,that are in the employees DivisionIdList (divisions he has access to.)  DEV-3504
                let AssetIdList = (from dv in context.AssetDivisions.Where(div => div.AssetId == e.AssetId && div.IsDeleted == false && Employee_DivisionIdList.Contains(div.DivisionId)) select dv.AssetId).ToList<Guid>()

                join assetUsageInfo in
                                     (
                                         from e in context.AssetUsages
                                         from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
                                         where e.IsDeleted == false
                                         select new ModuleView.AssetUsageBO
                                         {
                                             AssetUsageId = e.AssetUsageId,SiteId = e.SiteId,AssetId = e.AssetId,AssetUsageTypeId = e.AssetUsageTypeId,ImportId = e.ImportId,IsDeleted = e.IsDeleted,Created = e.Created,LastModified = e.LastModified,ModifiedByEmployeeId = e.ModifiedByEmployeeId,CreatedByEmployeeId = e.CreatedByEmployeeId,CreatedByEmployeeName = (!string.IsNullOrEmpty(cbu.FirstName)) ? cbu.LastName + "," + cbu.FirstName : cbu.LastName,IsDirty = false,IsNew = false,}
                                     ) on e.AssetId equals assetUsageInfo.AssetId into assetUsageInfos


                join assetExtendedFieldInfo in
                (
                    from e in context.AssetExtendedFields
                    from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
                    where e.IsDeleted == false
                    orderby e.FieldName
                    select new ModuleView.AssetExtendedFieldBO
                    {
                        AssetExtendedFieldId = e.AssetExtendedFieldId,FieldName = e.FieldName,FieldLabel = e.FieldLabel,FieldValue = e.FieldValue,FieldDataType = e.FieldDataType,}
                ) on e.AssetId equals assetExtendedFieldInfo.AssetId into assetExtendedFieldInfos

                join assetDivisionInfo in
                (
                    from e in context.AssetDivisions
                    from d in context.Divisions.Where(emp => emp.DivisionId == e.DivisionId && emp.IsDeleted == false)
                    from a in context.Assets.Where(emp => emp.AssetId == e.AssetId && emp.IsDeleted == false)
                    from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
                    where e.IsDeleted == false
                    select new ModuleView.AssetDivisionBO
                    {
                        AssetDivisionId = e.AssetDivisionId,DivisionId = e.DivisionId,DivisionName = d.DivisionName,AssetName = a.Name,}
                ) on e.AssetId equals assetDivisionInfo.AssetId into assetDivisionInfos


                where e.SiteId == Base_ContextSiteId
                        && (IsRestrictedByDivision == false || (IsRestrictedByDivision == true && (Base_ContextEmployee_IsForAllDivisions == true || AssetIdList.Contains(e.AssetId) || IsForAll_AssetIdList.Contains(e.AssetId)))) //from outer apply
                select new ModuleView.AssetBO
                {
                    AssetId = e.AssetId,AssetTypeId = e.AssetTypeId,Name = e.Name,Description = e.Description,UniqueIdentity = e.UniqueIdentity,StatusId = e.StatusId,CompanyId = e.CompanyId,Make = e.Make,Model = e.Model,Year = e.Year,SerialNumber = e.SerialNumber,PhoneNumber = e.PhoneNumber,Email = e.Email,IsActive = e.IsActive,BlockedTimeIsEnabled = e.BlockedTimeIsEnabled,IsForAllDivisions = e.IsForAllDivisions,AssetTypeName = e.AssetTypeName,StatusName = e.StatusName,CompanyName = e.CompanyName,ModifiedByEmployeeName = e.ModifiedByEmployeeName,NumCaptainsOnBoard = (e.CaptainNum == null) ? 0 : (int)e.CaptainNum,ActivityTimeInMin = e.TotalDurationInMin,AssetUsageInfo = assetUsageInfos,AssetExtendedFieldInfo = assetExtendedFieldInfos,AssetDivisionInfo = assetDivisionInfos,DivisionDelimitedString = "",//must be here to avoid error when sorting. Sort is done in BA code.
                };

    if (string.IsNullOrEmpty(where_clause))
    {
        where_clause = DataFilterBA.GetFilterWhereClause(context,filter,"ASSET",Base_ContextEmployeeId,Base_ContextSiteId,"LINQ");
    }
    int SkipRows = (PageNumber - 1) * PageSize;

    if (PassedAssetIdList.Count == 0)
    {
        RecordCount = query.Where(where_clause).Select(d => d.AssetId).distinct().Count();

        //RecordCount = query.Where(where_clause).GroupBy(test => test.AssetId)
        //                  .Select(grp => grp.FirstOrDefault()).Count();

        query = query.Where(where_clause).OrderBy(OrderByField + (IsDescending ? " descending" : ""));
    }
    else
    {
        RecordCount = query.Where(x => PassedAssetIdList.Contains(x.AssetId)).Where(where_clause).Select(d => d.AssetId).distinct().Count();
        query = query.Where(x => PassedAssetIdList.Contains(x.AssetId)).Where(where_clause).OrderBy(OrderByField + (IsDescending ? " descending" : ""));
    }


    List<ModuleView.AssetBO> items = new List<ModuleView.AssetBO>();
    if (PageSize == -1)
    {
        items = query.ToList<ModuleView.AssetBO>();
    }
    else
    {
        items = query.Skip(SkipRows).Take(PageSize).ToList<ModuleView.AssetBO>();
    }

    System.Data.Entity.Infrastructure.Interception.DbInterception.Remove(interceptor);
    if (items != null && items.Count > 0)
    {
        items = items.GroupBy(test => test.AssetId)
           .Select(grp => grp.FirstOrDefault())
           .ToList();

        return items;
    }
    return new List<ModuleView.AssetBO>();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。