2

我有一个“菜单”表,其中有一个 ParentId 列。我的 LINQ 查询就在下面。

    public IEnumerable<MenuTableObject> GetMenus ( int? parentId ) {
        var result = ( from m in _db.Menus
                       join ml in _db.MenuLanguages on m.Id equals ml.MenuId
                       join l in _db.Languages on ml.LanguageId equals l.Id
                       where l.Code == Thread.CurrentThread.CurrentCulture.Name
                             && m.ParentId == ( parentId.HasValue ? parentId : null )
                       select new MenuTableObject {
                           Action = m.Action,
                           Controller = m.Controller,
                           Id = m.Id,
                           Title = ml.Title,
                           SubMenus = this.GetMenus( m.Id )
                       } );

        return result;
    }

这是 MenuTableObject 类。

public class MenuTableObject {
    public int Id { get; set; }
    public string Title { get; set; }
    public string Controller { get; set; }
    public string Action { get; set; }
    public IEnumerable<MenuTableObject> SubMenus { get; set; }
}

这是我在下面得到的例外。

LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable`1[IstanbulHairCenter.Data.Service.MenuTableObject] GetMenus(System.Nullable`1[System.Int32])' method, and this method cannot be translated into a store expression.

我该怎么做才能克服这个问题?

4

2 回答 2

0

根据经验,您不能在任何 EFIQueryable查询中使用自定义函数(可能存在扩展点,但不确定)。

每个IQueryable查询都是一个表达式树,而不是一个函数(请注意,IQueryable Where()需要一个Expression<Func<T, bool>>而不是Func<T, bool>)。树被具体实现(在本例中为实体框架)分析并映射为 SQL 字符串。

每个映射必须由实现者显式创建。EF 告诉您它不知道如何处理您的GetMenus()方法(即来自GetMenus()-> SQL 的映射不存在)。

解决方法是从数据库中提取所有相关数据,然后使用 LINQ to Object 而不是 LINQ to Entities 运行查询。

递归不是真正的原因。您需要在调用第一个递归之前的某个时间在您的实体上使用ToList()(或者AsEnumerable()- 虽然不确定)GetMenus()。或者您可以编写一个 StoredProc 或其他东西并将其从上下文或DbSet.

于 2012-07-18T00:18:53.547 回答
0

您必须遍历 LINQ 查询之外的结果以进行填充SubMenus,因为 EF 无法将GetMenus方法转换为 SQL。

public IEnumerable<MenuTableObject> GetMenus ( int? parentId ) {
    var result = ( from m in _db.Menus
                   join ml in _db.MenuLanguages on m.Id equals ml.MenuId
                   join l in _db.Languages on ml.LanguageId equals l.Id
                   where l.Code == Thread.CurrentThread.CurrentCulture.Name
                         && m.ParentId == ( parentId.HasValue ? parentId : null )
                   select new MenuTableObject {
                       Action = m.Action,
                       Controller = m.Controller,
                       Id = m.Id,
                       Title = ml.Title
                   } ).ToList();

    foreach(var menu in result)
    {
        menu.SubMenus = this.GetMenus(menu.Id);
    }

    return result;
}
于 2012-07-18T00:19:49.063 回答