簡體   English   中英

帶有過濾器的 C# 中的 MongoDB Linq 查詢

[英]MongoDB Linq query in C# with filters

我正在嘗試對幾個 Mongo 集合進行 LINQ 查詢。 必須根據 ApplicationId 加入所有集合,並且必須完成外部加入 - 以便也返回沒有狀態的人員。 JOIN 部分及其周圍的一切都按預期工作。 問題是,當我向其中一個集合添加過濾器時,整個事情都會中斷

An exception of type 'System.ArgumentException' occurred in System.Linq.Expressions.dll but was not handled in user code: 'Expression of type 'System.Collections.Generic.IEnumerable`1[CDM.Person]' cannot be used for parameter of type 'System.Linq.IQueryable`1[CDM.Person]' of method 'System.Linq.IQueryable`1[CDM.Person] Where[Person](System.Linq.IQueryable`1[CDM.Person], System.Linq.Expressions.Expression`1[System.Func`2[CDM.Person,System.Boolean]])''

這是我的查詢

var applications = _dbContext.GetCollection<Application>(typeof(Application).Name).AsQueryable().Where(
                x => x.OrganizationID == TokenContext.OrganizationID);

var persons = _dbContext.GetCollection<Person>(typeof(Person).Name).AsQueryable().Where(p =>p.FirstName == "j");
var statuses = _dbContext.GetCollection<ApplicationStatus>(typeof(ApplicationStatus).Name).AsQueryable();
var mortgages = _dbContext.GetCollection<Mortgage>(typeof(Mortgage).Name).AsQueryable();

            var statusQuery = from a in applications
                                join p in persons on a.ApplicationID equals p.ApplicationID 
                                join s in statuses on a.ApplicationID equals s.ApplicationID into pas
                                join m in mortgages on a.ApplicationID equals m.ApplicationID into morgs
                                from subWHatever in pas.DefaultIfEmpty()
                              select new ApplicationStatusProjection
                              {
                                  ApplicationId = a.ApplicationID,
                                  FirstName = p.FirstName,
                                  LastName = p.Surname,
                                  Prefix = p.Prefix,
                                  DateOfBirth = p.DateOfBirth,
                                  Initials = p.Initials,
                                  PostalCode = p.Addresses.First().PostalCode,
                                  MortgageAmount = morgs.Sum(i => i.MortgageTotal) ?? 0,
                                  StatusExpireAt = subWHatever.ExpireAt ?? DateTime.MinValue,
                                  StatusMessageText = subWHatever.MessageText ?? "",
                                  StatusMessage = subWHatever.MessageStatus ?? ""

                              };

            if (!String.IsNullOrEmpty(orderBy))
            {
                statusQuery = statusQuery?.OrderBy(orderBy);
            }

            if (nrOfRecords != null)
            {
                statusQuery = statusQuery?.Take(nrOfRecords.Value);
            }

            // Execute the query
            var result = statusQuery?.ToList();
            return result;

我遵循這里的指南https://mongodb.github.io/mongo-csharp-driver/2.6/reference/driver/crud/linq/我也試過這個

var statusQuery = 
    from a in applications
       join p in persons on a.ApplicationID equals p.ApplicationID into pa
    from paObject in pa.DefaultIfEmpty()
       join s in statuses on paObject.ApplicationID equals s.ApplicationID into pas

但我得到了和以前一樣的錯誤。

先感謝您。

因此,經過可能的試用后,我發現由於 LINQ 查詢轉換為 Mongo 查詢的方式,您無法在加入之前進行過濾。 對此的解決方法是在 statusQuery 對象上進行過濾。 在這種情況下,過濾必須發生在投影對象上(因此需要一個新的過濾器)。 下面看看我是如何解決的:

 //get collections
            var applications = _dbContext.GetCollection<Application>(typeof(Application).Name).AsQueryable().Where(
                x => x.OrganizationID == TokenContext.OrganizationID);
            var persons = _dbContext.GetCollection<Person>(typeof(Person).Name).AsQueryable();
            var statuses = _dbContext.GetCollection<ApplicationStatus>(typeof(ApplicationStatus).Name).AsQueryable();
            var mortgages = _dbContext.GetCollection<Mortgage>(typeof(Mortgage).Name).AsQueryable();

            //query
            var query = from a in applications
                              join p in persons on a.ApplicationID equals p.ApplicationID
                              join s in statuses on a.ApplicationID equals s.ApplicationID into applicationStatusView
                              join m in mortgages on a.ApplicationID equals m.ApplicationID into morgs
                              from subStatus in applicationStatusView.DefaultIfEmpty()
                              select new ApplicationStatusProjection
                              {
                                  ApplicationId = a.ApplicationID,
                                  FirstName = p.FirstName,
                                  LastName = p.Surname,
                                  Prefix = p.Prefix,
                                  DateOfBirth = p.DateOfBirth,
                                  Initials = p.Initials,
                                  Addresses = p.Addresses ?? new List<Address>(),
                                  PostalCode = p.Addresses.First().PostalCode,
                                  MortgageAmount = morgs.Sum(i => i.MortgageTotal) ?? 0,
                                  StatusExpireAt = subStatus.ExpireAt ?? DateTime.MinValue,
                                  StatusMessageText = subStatus.MessageText ?? "",
                                  StatusMessage = subStatus.MessageStatus ?? "",
                                  StatusDate = subStatus.StatusDate

                              };

            //filter & order
            var filteredResult = ApplyFilters(query, searchCriteria);

            if (!String.IsNullOrEmpty(orderBy))
            {
                filteredResult = filteredResult?.OrderBy(orderBy);
            }

            if (nrOfRecords != null)
            {
                filteredResult = filteredResult?.Take(nrOfRecords.Value);
            }

            // Execute the query
            var result = filteredResult?.ToList();
            return result;

並應用過濾器(可能有更聰明的方法來做到這一點):

 private IQueryable<ApplicationStatusProjection> ApplyFilters(IQueryable<ApplicationStatusProjection> query, ApplicationStatusProjectionSearch searchCriteria)
        {
            if (!string.IsNullOrEmpty(searchCriteria.FirstName))
            {
                query = query.Where(x => x.FirstName.ToLower().StartsWith(searchCriteria.FirstName));
            }

            if (!string.IsNullOrEmpty(searchCriteria.LastName))
            {
                query = query.Where(x => x.LastName.ToLower().StartsWith(searchCriteria.LastName));
            }

            if (!string.IsNullOrEmpty(searchCriteria.PostalCode))
            {
                query = query.Where(x => x.Addresses.Any(a => a.PostalCode.ToLower().StartsWith(searchCriteria.PostalCode)));
            }
//other irrelevant filters
            return query;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM