无法在linq查询

时间:2016-05-11 15:28:50

标签: c# entity-framework linq

使用EF6,MVC5,C#

在评论和帖子中更新了其他人的建议

模型 (为简洁而简化)

public class ItemModel
{
    [Key]
    public int ID { get; set; }
    public string Description { get; set; }
    public string ModelNum { get; set; }

    [ForeignKey("SubCategory")]
    public Int32 SubCategoryId { get; set; }
    public SubCategory subCategory { get; set; }

    [Display(Name = "Manufacturer")]
    [ForeignKey("Manufacturer")]
    public Int32 ManufacturerId { get; set; }
    public Manufacturer manufacturer { get; set; }
}

public class Category
{
    [Key]
    public int ID { get; set; }
    public string CategoryName { get; set; }
    public virtual ICollection<SubCategory> SubCategories { get; set; }
}

public class SubCategory
{
    [Key]
    public int ID { get; set; }
    public string SubCategoryName { get; set; }

    [ForeignKey("Category")]
    [Display(Name = "Primary Category")]
    public int CategoryID { set; get; }
    public virtual Category Category { get; set; }
}

public class Manufacturer
{
    [Key]
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

控制器 编辑以简化问题

public IActionResult Index()
{
   var items = from i in _context.ItemModel
                    .Include(i => i.Manufacturer)
                    .Include(i => i.SubCategory)
                    .Include(i => i.SubCategory.Category)
                    .Where(a => a.Description.Contains("usb") ||
                                a.Manufacturer.Name.Contains("bas") ||         // <-8
                                a.SubCategory.SubCategoryName.Contains("len")  // <-9
                                )
                    select i;

    return View(items);
}

如您所见,我使用三个包含来访问关键字搜索的嵌套对象。硬编码一些where子句证明了我的问题。如果我删除第8行或第9行,那么它运行正常。如果我按所示运行(所有三行都在行),我会收到以下错误:

  

InvalidCastException:无法转换类型为&#39; System.Linq.Expressions.FieldExpression&#39;的对象。输入&#39; System.Linq.Expressions.ParameterExpression&#39;。   Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.IncludeExpressionVisitor.VisitMethodCall(MethodCallExpression expression)

我的包含或结构出了什么问题?

下面的堆栈跟踪:

InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.FieldExpression' to type 'System.Linq.Expressions.ParameterExpression'.
Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.IncludeExpressionVisitor.VisitMethodCall(MethodCallExpression expression)
System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
Microsoft.Data.Entity.Query.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
System.Linq.Expressions.ExpressionVisitor.VisitArguments(IArgumentProvider nodes)
System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.IncludeExpressionVisitor.VisitMethodCall(MethodCallExpression expression)
System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
Microsoft.Data.Entity.Query.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
Microsoft.Data.Entity.Query.RelationalQueryModelVisitor.IncludeNavigations(IncludeSpecification includeSpecification, Type resultType, LambdaExpression accessorLambda, Boolean querySourceRequiresTracking)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.IncludeNavigations(QueryModel queryModel, IReadOnlyCollection`1 includeSpecifications)
Microsoft.Data.Entity.Query.RelationalQueryModelVisitor.IncludeNavigations(QueryModel queryModel, IReadOnlyCollection`1 includeSpecifications)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.IncludeNavigations(QueryModel queryModel)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
Microsoft.Data.Entity.Storage.Database.CompileQuery[TResult](QueryModel queryModel)
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass18_0`1.<CompileQuery>b__0()
Microsoft.Data.Entity.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
Microsoft.Data.Entity.Query.Internal.QueryCompiler.CompileQuery[TResult](Expression query)
Microsoft.Data.Entity.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
Microsoft.Data.Entity.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
Remotion.Linq.QueryableBase`1.GetEnumerator()
Asp.ASPV__Views_ItemModels_Index_cshtml.<ExecuteAsync>d__25.MoveNext() in Index.cshtml
@foreach (var item in Model) {
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.Razor.RazorView.<RenderPageAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
Microsoft.AspNet.Mvc.Razor.RazorView.<RenderAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.ViewFeatures.ViewExecutor.<ExecuteAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.ViewResult.<ExecuteResultAsync>d__24.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeResultAsync>d__56.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeResultFilterAsync>d__55.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAllResultFiltersAsync>d__54.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeResourceFilterAsync>d__49.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAsync>d__44.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.<RouteAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Routing.Template.TemplateRoute.<RouteAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Routing.RouteCollection.<RouteAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.IISPlatformHandler.IISPlatformHandlerMiddleware.<Invoke>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Diagnostics.Entity.MigrationsEndPointMiddleware.<Invoke>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Diagnostics.Entity.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Diagnostics.Entity.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()

2 个答案:

答案 0 :(得分:1)

根据@RobertMcKee评论的想法,我在我的电脑上做了一些测试。 以下是供您参考的解决方案。

public class ItemModel
    {
        [Key]
        public int ID { get; set; }
        public string Description { get; set; }
        public string ModelNum { get; set; }

        //[ForeignKey("Category")]
        //public Int32 CategoryId { get; set; }
        //public virtual Category Category { get; set; }

        [ForeignKey("SubCategory")]
        public Int32 SubCategoryId { get; set; }
        public virtual SubCategory SubCategory { get; set; }

        [ForeignKey("Manufacturer")]
        public Int32 ManufacturerId { get; set; }
        public virtual Manufacturer Manufacturer { get; set; }
    }

    public class Category
    {
        [Key]
        public int ID { get; set; }
        public string CategoryName { get; set; }
        public virtual ICollection<SubCategory> SubCategories { get; set; }
    }

    public class SubCategory
    {
        public int ID { get; set; }
        public string SubCategoryName { get; set; }

        [ForeignKey("Category")]
        public int CategoryID { set; get; }
        public virtual Category Category { get; set; }
    }

    public class Manufacturer
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }

过滤器类似于

var items = from i in context.ItemModels
                .Include(i => i.Manufacturer)
                .Include(i => i.SubCategory)
                .Include(i => i.SubCategory.Category)
                        select i;

            // Apply filter if search query was entered
            if (!String.IsNullOrEmpty(searchString))
            {
                string[] searchWords = searchString.Split(' ');

                foreach (var word in searchWords)
                {
                    items = items.Where(s => s.Description.Contains(word) ||
                                 s.SubCategory.Category.CategoryName.Contains(word) || 
                                 s.SubCategory.SubCategoryName.Contains(word) ||
                                 s.Manufacturer.Name.Contains(word) ||
                                 s.ModelNum.Contains(word)
                                 );
                }
            }
            return items;

我在ItemModel中评论类别的原因是,如果我们在ItemModel中放入Category和Subcategory,EF Migration会在下面显示警告。

Introducing FOREIGN KEY constraint 'FK_dbo.ItemModels_dbo.SubCategories_SubCategoryId' on table 'ItemModels' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.

由于我们必须将ItemModel放入子类别,因此从类ItemModel中删除属性Category。

答案 1 :(得分:0)

从未弄清楚为什么我无法在Linq查询中访问多个子类,但我确实想出了一个解决方案,使用辅助类来展平结构。发布此信息以帮助处于类似情况的其他人。

新增,附加类

public class ItemDisplay
{
    [Key]
    public int id { get; set; }
    public int m_ItemID { get; set; }
    public string m_ItemDesc { get; set; }
    public string m_ManfName { get; set; }
    public string m_CategoryName { get; set; }
    public string m_SubCategoryName { get; set; }
}

<强>控制器

[Authorize()]
public IActionResult SearchItems(string searchString)
{
    var ItemList = from i in _context.ItemModel
                    select new ItemDisplay
                    {
                        m_ItemID = i.ID,
                        m_ItemDesc = i.Description,
                        m_CategoryName = i.SubCategory.Category.CategoryName,
                        m_ManfName = i.Manufacturer.Name,
                        m_SubCategoryName = i.SubCategory.SubCategoryName,
                    };

    // Apply filter if search query was entered
    if (!String.IsNullOrEmpty(searchString))
    {
        // Sanitize search string
        searchString = searchString.Trim();
        searchString = System.Text.RegularExpressions.Regex.Replace(searchString, @"[^0-9a-zA-Z\._\s]", " ");
        searchString = System.Text.RegularExpressions.Regex.Replace(searchString, @"[\s]+", " ");
        string[] searchWords = searchString.Split(' ');

        foreach (var word in searchWords)
        {
            ItemList = ItemList.Where(s => s.m_ItemDesc.Contains(word) ||
                           s.m_ManfName.Contains(word) ||
                           s.m_CategoryName.Contains(word) ||
                           s.m_SubCategoryName.Contains(word)
                        );
        }
    }

    ItemList = ItemList.OrderBy(r => r.m_ItemDesc);
    return View(ItemList);
}

查看

@model IEnumerable<LabInventory.Models.ItemDisplay>

@* example *@

@foreach (var item in Model )
{
   @Html.DisplayFor(modelItem => item.m_ItemDesc)
}

现在,搜索可以在ItemDisplay类的所有成员中正常运行。