Linq to Entities - where语句抛出System.NotSupported Exception

时间:2017-09-19 16:32:10

标签: c# entity-framework linq

Sub GetFlows()

Dim rng As Range
Dim row As Range
Dim cell As Range
Dim dem1 As String
Dim WhereCell As Range
Dim ws As Excel.Worksheet
Dim iIndex As Integer

Dim valueRng As Range
Dim x As Long
Dim y As Long

Set rng = Range("A9:A200") ' should specify a sheet here, presumably Summary?

For Each ws In ThisWorkbook.Worksheets
    If ws.Name <> "summary" Then
        For x = 1 To rng.Rows.Count
            dem1 = rng.Cells(x).Value
            If dem1 <> vbNullString Then
                Set WhereCell = ws.Range("A9:A200").Find(dem1, lookat:=xlPart)
                If Not WhereCell Is Nothing Then
                    Workbooks("GetFilenames v2.xlsm").Worksheets(dem1).Range("A1").CurrentRegion.Copy
                    WhereCell.Offset(, 2).PasteSpecial Paste:=xlPasteValues
                End If
            End If
        Next x
    End If
Next ws

End Sub

}

问题在于where子句。 var entity = from document in db.Context.DocumentEntity join product in db.Context.ProductEntity on document.ProductId equals product.Id join partner in db.Context.PartnerEntity on product.PartnerId equals partner.Id select new { document, product, partner } into t1 where request.PartnerFilter.Contains(t1.partner.Name) group t1 by t1.document.Date into rp select new { PartnerName = rp.FirstOrDefault().partner.Name, Date = rp.FirstOrDefault().document.Date, Income = rp.Sum(x => x.document.Income), Click= rp.Sum(x => x.document.Click) }; result = ToDataTable(entity.OrderByDescending(d=>d.Date).ToList()); public static DataTable ToDataTable<T>(List<T> items) { DataTable dataTable = new DataTable(typeof(T).Name); PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in Props) { var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType); dataTable.Columns.Add(prop.Name, type); } foreach (T item in items) { var values = new object[Props.Length]; for (int i = 0; i < Props.Length; i++) { values[i] = Props[i].GetValue(item, null); } dataTable.Rows.Add(values); } return dataTable; 是一个字符串数组,可能为null。我需要检查其中是否包含request.PartnerFilter。 Sql Where-In的种类。最后,entity.ToList()抛出System.NotSupported Exception。如何完成过滤?

3 个答案:

答案 0 :(得分:4)

如果要在EF查询表达式树中使用Contains,则需要确保该变量不为null。并且您需要在查询之外执行此操作(以及需要应用的条件)。

例如:

var partnerFilter = request.PartnerFilter ?? Enumerable.Empty<string>();
bool applyPartnerFilter = partnerFilter.Any();

var entity =
    ...
    where (!applyPartnerFilter || partnerFilter.Contains(t1.partner.Name))
    ...

但在我看来,在查询之外应用可选过滤器会好得多,例如:

var partners = db.Context.PartnerEntity.AsQueryable();
if (request.PartnerFilter != null && request.PartnerFilter.Any())
    partners = partners.Where(partner => request.PartnerFilter.Contains(partner.Name));

var entity =
...
join partner in partners on product.PartnerId equals partner.Id
...

(没有where

答案 1 :(得分:2)

将此请求部分排除在等式之外,因为实体框架不知道如何处理Request对象,它可以处理字符串,字符串数组等。

string[] strArray=request.PartnerFilter;

var entity =
from document in db.Context.DocumentEntity
join product in db.Context.ProductEntity on document.ProductId equals product.Id
join partner in db.Context.PartnerEntity on product.PartnerId equals partner.Id
select new
{
   document,
   product,
   partner
} into t1
//Check if null
where strArray!=null && strArray.Any() && strArray.Contains(t1.partner.Name)
group t1 by t1.document.Date into rp
select new
{
   PartnerName = rp.FirstOrDefault().partner.Name,
   Date = rp.FirstOrDefault().document.Date,
   Income = rp.Sum(x => x.document.Income),
   Click= rp.Sum(x => x.document.Click)
};

此外,使用导航属性而不是连接

答案 2 :(得分:1)

您使用SQL WHERE IN ()子句与Contains正确无误。您唯一的问题是可能的null异常。

如果数组为空,会发生什么?你想拥有所有价值观吗?如果数组为空,请使用true,否则false

试试这个:

string[] partnerNames = request.PartnerFilter;

var entity =
   from document in db.Context.DocumentEntity
   join product in db.Context.ProductEntity on document.ProductId equals product.Id
   join partner in db.Context.PartnerEntity on product.PartnerId equals partner.Id
   select new
   {
       document,
       product,
       partner
   } into t1
   where partnerNames?.Contains(t1.partner.Name) ?? true
   group t1 by t1.document.Date into rp
   select new
   {
       PartnerName = rp.FirstOrDefault().partner.Name,
       Date = rp.FirstOrDefault().document.Date,
       Income = rp.Sum(x => x.document.Income),
       Click= rp.Sum(x => x.document.Click)
   };

WHERE IN - 作为查询语法

var selected = from document in Document 
               where new[] {"Paul", "Peter"}.Contains(document.UserName)
               select document

WHERE IN - 作为方法语法

var selected = Document
               .Where(d => new[] ["Paul","Peter"}.Contains(d.UserName))