2012-05-09 61 views
4

對於開發中的Web應用程序(ASP.Net MVC),我使用了telerik網格。網格綁定到我的列表的IQueryable,因爲它是一個大表,我希望telerik將它應用於列表中的過濾器,然後執行此結果,而不是下載10,000行(連接表),然後使用過濾器,只使用行。在Asp MVC Telerik Grid和Entity Framework中處理Enums

我正在使用(我真的需要它爲這個頁面,它是一個關鍵特性)過濾器/網格的順序。

主列之一(確定數據的種類)是一個枚舉。

問題是,當我試圖過濾/排序它時,我得到一個"Specified type member is not supported in linq to entities"

我必須將它綁定在enum(而不是映射的int)上,因爲如果我使用id,filters/order by將在int上,並且我不能指望用戶知道id外表。

我只是不能再實現自己所有的網格參數(位於url)(我想,它要麼是我做的一切,要麼沒有)並正確地過濾它,命令正確)。

您是否有解決方法的想法?

回答

5

我不知道你的實體模型的樣子,但我會假設你已經是這樣的型號:

public partial class Project 
{  
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int Status { get; set; } 
} 

和狀態屬性表示你的枚舉值那麼你該枚舉:

public enum ProjectStatuses 
{ 
    Current = 1, 
    Started = 2, 
    Stopped = 3, 
    Finished = 4, 
} 

然後,只需創建新的視圖模型是這樣的:

public class ProjectDetails 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public int Status { get; set; } 
     public ProjectStatuses StatusValue { get { return (ProjectStatuses) Status; } } 
     // This property to display in telerik ClientTemplate 
     public string StatusName { get { return Enum.GetName(typeof (ProjectStatuses), Status); } }    
    } 

因爲我愛擴展方法我將添加這一個:

public static class ModelListExtensions 
{ 
     public static IQueryable<ProjectDetails> ToViewModelDetails(this IQueryable<Project> modelList) 
     { 
      return modelList.Select(m => new ProjectDetails 
              { 
               Id = m.Id, 
               Name = m.Name, 
               Status = m.Status, 
               }; 
     } 
} 

更新:

這裏是控制器

public ActionResult Index() 
    { 
     int total; 
     var viewModel = getGridList(out total); 
     ViewBag.Total = total; 
     return View(viewModel); 
    } 

    //this Action to get ajax pages 
    [GridAction(EnableCustomBinding = true)] 
    public ActionResult ReGetIndex(GridCommand command, int roleId) 
    { 
     int total; 
     var list = getGridList(out total, roleId, command); 
     return View(new GridModel {Data = list, Total = total}); 
    } 


    private IEnumerable<ProjectDetails> getGridList(out int total, GridCommand command = null) 
    { 
     command = command ?? new GridCommand {Page = 1}; 
    foreach (var descriptor in command.SortDescriptors) 
    { 
     if (descriptor.Member == "StatusValue") 
      descriptor.Member = "Status"; 

    } 
    foreach (FilterDescriptor descriptor in command.FilterDescriptors) 
    { 
     if (descriptor.Member == "StatusValue") 
      descriptor.Member = "Status"; 
    } 

    var list = modelService.AllAsQuery() 
      .ToViewModelDetails() // To convert it to our ViewModel if we have one 
      .Where(command.FilterDescriptors); 

    total = list.Count(); 

    return (IEnumerable<ProjectDetails>) list.Sort(command.SortDescriptors) 
                .Page(command.Page - 1, command.PageSize) 
                .GroupBy(command.GroupDescriptors).ToIList(); 
} 

這是查看

@model IEnumerable<ProjectDetails> 
@{ 
    Html.Telerik() 
     .Grid(Model) 
     .Name("ProjectsGrid") 
     .Sortable() 
     .Filterable() 
     .EnableCustomBinding(true) 
     .DataBinding(dataBinding => dataBinding 
             .Ajax() 
             .Select("ReGetIndex", "Projects")) 
     .Pageable(page => page.Style(GridPagerStyles.PageSizeDropDown | GridPagerStyles.NextPreviousAndNumeric).Total(ViewBag.Total)) 
     .Columns(column => 
        { 
         column.Bound(m => m.Id).Hidden(true); 
         column.Bound(m => m.Name); 
         column.Bound(m => m.StatusValue).ClientTemplate("<#= StatusName #>"); 
        }) 
     .Render(); 
} 

更新:

如果要強制執行至少一個排序順序,您可以使用這樣的事情:

if (!command.SortDescriptors.Any()) 
{ 
    command.SortDescriptors.Add(new SortDescriptor {Member = "YourDefaultProperty"}); 
} 
+0

當將網格綁定到我的模型的屬性時,可以這樣做嗎 – J4N

+0

@ J4N如果您不想添加ViewModel類,那麼您可以只在部分類中擴展模型,在我們的例子中放置其他兩個屬性「'StatusValue''和'StatusName'」 –

+0

可以肯定的是,你能否真正向我展示如何將數據綁定到視圖中的網格? – J4N

0

你真的沒有選擇(或幾個煩人的選擇)

無論您使用的一類,而不是枚舉(但如果你使用一個枚舉,這是因爲它是更好)。

或者你「僞排序」你的枚舉,並使用映射的int。

public enum TT 
    { 
     Brown = 0, 
     Green = 1 
    } 

當然,你必須檢查實際DATAS(映射INT)在你的數據庫,並更新它們,以符合新的訂單(不影響不能改變枚舉順序)。每次你想在現有的枚舉值之間插入一個值時,你必須這樣做。

或者你等待下一次EF/LINQ/C#版本,它應該有linq2entities支持ENUM

+0

我只是不能,t他的網站是本地化的,所以有時候會是布朗先來,有時候會是綠色的。而且我不能在這裏上課,數據庫設計在幾個月前已經被鎖定,以滿足API /備份/需求(就像你說的,這真的是DB的最佳選擇,我明白會發生,但它應該是一個解決方法 – J4N