Linq语句中的DefaultIfEmpty问题

时间:2018-03-19 21:02:18

标签: c# linq ef-core-2.0

有人可以向我解释这里出了什么问题。我使用Linq to Sql来创建一个非常讨厌的查询。

我遇到的问题是我需要在某些表上保持联接 (使用DefaultIfEmpty)我需要从中返回一个特定的对象 DefaultIfEmpty(new SomeObject(){...}) 以便稍后我可以加入它。

我的问题是DefaultIfEmpty总是返回null。所以我检查了一些虚拟数据作为POC,它的工作原理

实施例

我似乎无法找到用于获取下面示例代码的链接,我只是稍微修改了一下,以便为OrderConfirmed添加额外的连接所以当运行它时,它按预期工作

List<Book> bookList = new List<Book>
{
  new Book{BookID=1, BookNm="DevCurry.com Developer Tips"},
  new Book{BookID=2, BookNm=".NET and COM for Newbies"},
  new Book{BookID=3, BookNm="51 jQuery ASP.NET Recipes"},
  new Book{BookID=4, BookNm="Motivational Gurus"},
  new Book{BookID=5, BookNm="Spiritual Gurus"}
};

List<Order> bookOrders = new List<Order>
{
    new Order{OrderID=1, BookID=1, PaymentMode="Cheque"},
    new Order{OrderID=2, BookID=5, PaymentMode="Credit"},
    new Order{OrderID=3, BookID=1, PaymentMode="Cash"},
    new Order{OrderID=4, BookID=3, PaymentMode="Cheque"},
    new Order{OrderID=5, BookID=5, PaymentMode="Cheque"},
    new Order{OrderID=6, BookID=4, PaymentMode="Cash"}
};

List<OrderConfirmed> orderConfirmed = new List<OrderConfirmed>();


var orderForBooks = from bl in bookList
                    join ordr in bookOrders on bl.BookID equals ordr.BookID into a
                        from ordr in a.DefaultIfEmpty(new Order {BookID = -1, OrderID = 12, PaymentMode = "Cash Test" }) // return default value
                    join confirmed in orderConfirmed on ordr.OrderID equals confirmed.OrderID into c
                        from confirmed in c.DefaultIfEmpty(new OrderConfirmed() { OrderID = 12, Description = "Is this working"}) // no values in orderconfirmed so returning new object
                    select new
                               {
                                   bl,
                                   ordr,
                                   confirmed
                    };

因此,知道我正在尝试todo应该工作,在我的实际代码中,DefaultIfEmpty始终为null。我说得对,这应该有用吗? 也许需要注意的是我正在使用EFCORE

var formData = 
 await (from ccf in this.context.Set<BureauCountryCustomForm>()
          join ccfa in this.context.Set<EmployeeCustomFormAttributeHeader>() on ccf.BureauCountryFormId equals ccfa.BureauCountryFormId into ccfaJoin
          from ccfa in ccfaJoin.DefaultIfEmpty(new EmployeeCustomFormAttributeHeader()
                                                   {
                                                       HeaderId = -1,
                                                       BureauCountryFormId = 3,
                                                       CompanyFormId = -1,
                                                       EmployeeId = 1
                                                   })
          join cca in this.context.Set<BureauCountryCustomFormAttribute>() on ccf.BureauCountryFormId equals cca.BureauCountryFormId
          join edv in this.context.Set<EmployeeCustomFormValue>() on
              new { AttributeId = (int?)cca.BureauCountryFormAttributeId, HeaderId = (int?)ccfa.HeaderId } equals
              new { AttributeId = (int?)edv.FormAttributeId, HeaderId = (int?)edv.HeaderId } into edvJoin
          from edv in edvJoin.DefaultIfEmpty(new EmployeeCustomFormValue()
                                                 {
                                                     HeaderId = -1,
                                                     FormAttributeId = -1
                                                 })
          where ccf.CountryId == countryId && ccf.EmployeeLevel == true && ccfa.EmployeeId == employeeId
          select new { ccf, ccfa, cca, edv }).GroupBy(g => new { g.ccf.BureauCountryFormId, g.ccfa.HeaderId })
.Select(
_ => new CustomFormData
{
    Keys = new[] { _.Key.BureauCountryFormId, _.Key.HeaderId },
    FormName = _.First().ccf.FormName,
    EffectiveDate = _.First().ccfa.EffectiveDate,
    FormDataFields = _.Select(
                 f => new CustomFormDataField
                 {
                     AttributeId = f.cca.BureauCountryFormAttributeId,
                     FieldLabel = f.cca.FieldLabel,
                     IsMandatory = f.cca.IsMandatory,
                     FieldValue = f.edv.FieldValue,
                     ControlTypeId = (long)f.cca.ControlTypeId,
                     DropdownValues = f.cca.DropdownValues,
                     Order = f.cca.AttOrderNo,
                     ValidationRule = f.cca.ValidationRule,
                     ValidationExpression = f.cca.ValidationExpression
                 }).ToList()
}).ToListAsync();

1 个答案:

答案 0 :(得分:2)

问题在于:

from ccfa in ccfaJoin.DefaultIfEmpty(new EmployeeCustomFormAttributeHeader())

这样的查询构造只应该用于像db set这样的集合或者不是DefaultIfEmpty的查询,但是它是IEnumerable但是EF Core将它视为单个值(如果没有匹配,它真的在sql查询结果为null),无论它在哪里使用

您应将其更改为:

let ccfa = ccfaJoin.DefaultIfEmpty(new EmployeeCustomFormAttributeHeader())

它应该按预期工作。