2013-07-26 71 views
0

在我的模型類OwnedModule中,我將OwnerID作爲Guid。LINQ to Entities不識別該方法。 Guid造成麻煩?

還有另一個名爲BusinessUnit的模型類,它包含OwnedModule及其OwnerName中的相同Guid值。

我想告訴OwnedModule,其中包含有關硬件的細節,但有車主爲GUID值,而不是名稱的詳細信息,併爲了這個,我已經創建了一個視圖模型

public class OwnedModuleViewModel 
    { 
     public long Id { get; set; } 
     public string ModuleId { get; set; } 
     public string TypeName { get; set; } 
     public string KindName { get; set; } 
     public string Owner { get; set; } 
     public DateTime OwnershipStart { get; set; } 
    } 
    public class IndexOwnedModule 
    { 
     public List<OwnedModuleViewModel> OwnedModules { get; set; } 
    } 

到顯示所有這些細節在我的倉庫我有以下功能

public IndexOwnedModule GetAllOwnedModules() 
    { 

     var modulesList = new IndexOwnedModule(); 

     var modules = (_dbSis.OwnedModules.OrderBy(module => module.Id).Select(module => new OwnedModuleViewModel 
     { 
      Id = module.Id, 
      ModuleId = module.ModuleId, 
      TypeName = module.ModuleType.TypeName, 
      Owner = GetModuleOwner(module.ModuleOwnerId),//error here 
      OwnershipStart = module.Start 
     })); 

     modulesList.OwnedModules = modules.ToList(); 
     return modulesList; 

    } 

    public string GetModuleOwner(Guid id) 
    { 
     var ownedModule =_dbSis.Set<BusinessUnit>().FirstOrDefault(t => t.Id == id); 
     if (ownedModule != null) return ownedModule.Name; 
     return null; 
    } 

它不會是方便易以顯示GUID值的視圖中的用戶擁有者,所以我想取的,我有GetModuleOwnerName名稱。

但它似乎像我已經設置所有者的名稱到我的viewmodel視圖的方式是錯誤的,並且當我運行該應用程序時出現以下錯誤。

LINQ to Entities不識別方法'System.String GetModuleOwner(System.Guid)'方法,並且此方法不能轉換爲存儲表達式。

當我的評論,我已經設置所有者的值線(所有者= GetModuleOwner(module.ModuleOwnerId)),一切工作正常。

回答

3

當Entity Framework構建您的查詢時,它依賴於對傳遞的表達式樹的檢查。遇到方法調用時,它會嘗試使用(see this for the canonical methods)將其映射到等效的SQL方法。因爲實體框架不知道OwnedModuleViewModel.GetModuleOwner,它不能生成適當的SQL查詢。在這種情況下,簡單的辦法是嵌入你的方法在查詢確實不是調用的方法是什麼:

_dbSis.OwnedModules 
     .OrderBy(module => module.Id) 
     .Select(module => new OwnedModuleViewModel 
      { 
       Id = module.Id, 
       ModuleId = module.ModuleId, 
       TypeName = module.ModuleType.TypeName, 
       Owner = _dbSis.Set<BusinessUnit>() 
          .Where(t => t.Id == module.ModuleOwnerId) 
          .Select(t => t.Name).FirstOrDefault(), 
       OwnershipStart = module.Start 
      }); 

當然,這是假設_dbSis.Set<BusinessUnit>()相同DbContextDbSet<T>一部分,否則相同出現問題。

+0

這個工作,但它會更好,有業主使用方法設置,不使代碼看起來乾淨 – Cybercop

+0

@ Biplov13如果你有定義之間的關係'OwnerModule'和'BusinessUnit',你可以簡單地使用'OwnerModule'上的導航屬性來訪問'BusinessUnit'而不是做一個嵌入式選擇。但是我不能肯定地不知道你的模型是如何定義的。 –

+0

不幸的是,這裏沒有激動人心的屬性,但是非常感謝 – Cybercop

1

在Linq-To-Entities中,針對上下文的Linq語句被轉換爲SQL語句。將GetModuleOwner()方法轉換爲SQL顯然是不可能的。您需要首先獲取ModuleOwnerId,然後在另一個步驟中,對每個ModuleOwnerId調用GetModuleOwner()。

或者你可以調整你的查詢中使用聯接:

var modules = from m in _dbSis.OwnedModules 
       join b in _dbSis.BusinessUnit on m.ModuleOwnerId equals b.Id 
       order by m.Id 
       select new OwnedModuleViewModel { 
             Id = m.Id, 
             ModuleId = m.ModuleId, 
             TypeName = m.ModuleType.TypeName, 
             Owner = b.Name, 
             OwnershipStart = m.Start}; 

modulesList.OwnedModules = modules.ToList(); 

注:我沒有測試此所以它可能有一些小的語法錯誤。

+0

我認爲它會工作,減去(我認爲)'OwnedModuleViewModel()'。你真的需要堅持使用Entity Framework的對象初始化語法,否則它會報錯。 –

+0

很高興看到我使用的方法實際上正在使用,但我有點感覺相當複雜。也就像你說的小錯誤一樣存在,就像編輯器說的那樣,它期望**; **在第二行結尾,並且它不能在選擇中解析符號** m **和** b **。無論如何感謝您的選擇 – Cybercop

0

這可能是另一種選擇

var ownedModules = _dbSis.OwnedModules.OrderBy(module => module.Id).Select(module => new 
      { 
       Id = module.Id, 
       ModuleId = module.ModuleId, 
       TypeName = module.ModuleType.TypeName, 
       ModuleOwnerId = module.ModuleOwnerId, 
       OwnershipStart = module.Start 
      }).ToList().Select(m => new OwnedModuleViewModel 
      { 
       Id = m.Id, 
       ModuleId = m.ModuleId, 
       TypeName = m.TypeName, 
       Owner = GetModuleOwner(m.ModuleOwnerId), 
       OwnershipStart = m.OwnershipStart 
      }); 
      ownedModulesList.OwnedModules = ownedModules.ToList(); 
      return ownedModulesList; 
+0

使用該功能,也沒有複雜的查詢 – Cybercop

+0

你的新答案的問題是它非常無效。在查詢中嵌入方法允許查詢完成一次。你所提出的做一個查詢來獲得'OwnerModules',並且爲他們每個人發送另一個查詢來獲得所有者。如果你有5個模塊,你可以做6個查詢。如果你有100個模塊,你可以做101個查詢等。雖然它確實有效,但它不能很好地擴展。並調用'ToList'創建一個不必要的臨時列表。您可以將其替換爲'AsEnumerable'或將'Select'替換爲'List .ForEach'並更改具體化對象。 –

+0

感謝您的建議。 – Cybercop

相關問題