2013-03-22 90 views
-1

我一直在我的代碼中得到下面的錯誤,並且無法理解爲什麼它有問題將它翻譯成查詢,這很簡單。LINQ to Entities無法識別該方法,2儲存庫

我有2個儲存庫,AlbumAlbumImage,當我取一個專輯我想要一個封面,這是AlbumImages的子選擇。我在這裏做錯了什麼?

LINQ實體無法識別「)System.Linq.IQueryable`1 [Sogaard.us.Cosplay.Data.AlbumImage]取得(」的方法 方法,並且這種方法不能被翻譯成存儲表達。

專輯庫

public class AlbumRepository : IRepository<Album> 
    { 
     private CosplayEntities _entities; 
     private IRepository<AlbumImage> _imageRepository; 

     public AlbumRepository(CosplayEntities entities, IRepository<AlbumImage> imageRepository) 
     { 
      _entities = entities; 
      _imageRepository = imageRepository; 
     } 

     public IQueryable<Album> Get() 
     { 
      return (from a in _entities.Albums 
        select new Album() 
         { 
          Id = a.Id, 
          UserId = a.UserId, 
          Name = a.Name, 
          Created = a.Created, 
          LastEdit = a.LastEdit, 
          Description = a.Description, 
          Views = a.Views, 
          Location = a.Location, 
          Photoshoot = a.Photoshoot, 
          Cover = (from ai in _imageRepository.Get() where ai.AlbumId == a.Id orderby ai.Cover descending, ai.Id ascending select ai).FirstOrDefault(), 
         }); 
     } 
} 

AlbumImage庫

public class AlbumImageRepository : IRepository<AlbumImage> 
{ 
    private CosplayEntities _entities; 

    public AlbumImageRepository(CosplayEntities entities) 
{ 
    _entities = entities; 
} 

public IQueryable<AlbumImage> Get() 
{ 
    return (from ai in _entities.AlbumImages 
      select new AlbumImage() 
       { 
        Id = ai.Id, 
        AlbumId = ai.AlbumId, 
        UserId = ai.UserId, 
        Type = ai.Type, 
        Width = ai.Width, 
        Height = ai.Height, 
        Description = ai.Description, 
        Views = ai.Views, 
        Uploadet = ai.Uploadet, 
        LastView = ai.LastView, 
        Thumblink = ai.Thumblink, 
        Imagelink = ai.Imagelink, 
        Cover = ai.Cover 
       }); 
} 

這是我收到的

_albumImageRepository = new AlbumImageRepository(_entities); 
    _albumRepository = new AlbumRepository(_entities, _albumImageRepository); 
    _albumImagesTagRepository = new AlbumImagesTagRepository(_entities); 
.... 

    var album = _albumRepository.Get().Where(x => x.Id == image.AlbumId).FirstOrDefault(); 

更新錯誤代碼:我有評論 Cover = ...在我的IQueryable Get()中,所以它是2個簡單的選擇對象。 ,我仍然得到一些錯誤的

model.Albums = (from a in _albumRepository.Get() 
        orderby a.Id descending 
        select new AlbumDisplayModel() 
         { 
          Album = a, 
          ImageCount = _albumImageRepository.Get().Where(x => x.AlbumId == a.Id).Count(), 
          User = _userRepository.Get().Where(x => x.Id == a.UserId).FirstOrDefault() 
         }) 
         .Skip(AlbumsPrPage * (page - 1)) 
         .Take(AlbumsPrPage).ToList(); 

更新爲簡單的2:如果我重寫IQueryable的獲得()到下面做它工作得很好,有沒有真正應該如何沒有diffrence它被處理?

public IQueryable<Album> Get() 
{ 
    return (from a in _entities.Albums 
      select new Album() 
       { 
        Id = a.Id, 
        UserId = a.UserId, 
        Name = a.Name, 
        Created = a.Created, 
        LastEdit = a.LastEdit, 
        Description = a.Description, 
        Views = a.Views, 
        Location = a.Location, 
        Photoshoot = a.Photoshoot, 
        Cover = (from ai in _entities.AlbumImages where ai.AlbumId == a.Id orderby ai.Cover descending, ai.Id ascending select new AlbumImage() 
        { 
         Id = ai.Id, 
         AlbumId = ai.AlbumId, 
         UserId = ai.UserId, 
         Type = ai.Type, 
         Width = ai.Width, 
         Height = ai.Height, 
         Description = ai.Description, 
         Views = ai.Views, 
         Uploadet = ai.Uploadet, 
         LastView = ai.LastView, 
         Thumblink = ai.Thumblink, 
         Imagelink = ai.Imagelink, 
         Cover = ai.Cover 
        }).FirstOrDefault(), 
       }); 
} 

更新3:做了一個小測試,這個問題似乎是與實體框架,SE下面的代碼,該var linqAlbum = testClass.LinqAlbumGet().ToList();執行沒有任何問題,並返回正確的數據,var eeAlbum = testClass.EEAlbumGet().ToList();失敗,出現異常

LINQ實體無法識別方法 「System.Linq.IQueryable`1 [RepositoryTest.TestAlbumCover] EEImageGet()」 方法,並且這種方法不能被翻譯成表達商店。

我的測試腳本

class Program 
{ 
    static void Main(string[] args) 
    { 
     var linq = new LinqDataContext(); 
     var ee = new NewCosplayEntities(); 

     var testClass = new Test(linq, ee); 

     var linqAlbum = testClass.LinqAlbumGet().ToList(); 
     var eeAlbum = testClass.EEAlbumGet().ToList(); 
    } 
} 


    public class Test 
    { 
     public NewCosplayEntities ee { get; set; } 
     public LinqDataContext linq { get; set; } 

     public Test(LinqDataContext linq, NewCosplayEntities ee) 
     { 
      this.linq = linq; 
      this.ee = ee; 
     } 

     public IQueryable<TestAlbum> LinqAlbumGet() 
     { 
      return from a in linq.Albums 
        select new TestAlbum 
        { 
         Id = a.Id, 
         Name = a.Name, 
         Cover = (from i in LinqImageGet() where i.AlbumId == a.Id select i).FirstOrDefault() 
        }; 
     } 

     public IQueryable<TestAlbumCover> LinqImageGet() 
     { 
      return from i in linq.AlbumImages 
        select new TestAlbumCover() 
        { 
         Id = i.Id, 
         AlbumId = i.AlbumId 
        }; 
     } 

     public IQueryable<TestAlbum> EEAlbumGet() 
     { 
      return from a in ee.Albums 
        select new TestAlbum 
        { 
         Id = a.Id, 
         Name = a.Name, 
         Cover = (from i in EEImageGet() where i.AlbumId == a.Id select i).FirstOrDefault() 
        }; 
     } 

     public IQueryable<TestAlbumCover> EEImageGet() 
     { 
      return from i in ee.AlbumImages 
        select new TestAlbumCover() 
        { 
         Id = i.Id, 
         AlbumId = i.AlbumId 
        }; 
     } 
    } 

    public class TestAlbum 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public TestAlbumCover Cover { get; set; } 
    } 

    public class TestAlbumCover 
    { 
     public int Id { get; set; } 

     public int AlbumId { get; set; } 
    } 

回答

1

你的問題出現在Albumn的ItemRepository中。特別是因爲_entities不知道_imageRepository類型,因此它不知道如何將該類型轉換爲適當的TSQL腳本。在嘗試從水合對象的範圍訪問_ImageRepository.Get()而不是直接訪問數據庫實例之前,可以將_entities.Albums.ToList()強制將IQueryable強制爲IEnumerable。意識到你將會看到每個Album的n + 1數據庫對於AlbumImage子對象的請求。

public IQueryable<Album> Get() 
    { 
     return (from a in _entities.Albums 
       select new Album() 
        { 
         Id = a.Id, 
         UserId = a.UserId, 
         Name = a.Name, 
         Created = a.Created, 
         LastEdit = a.LastEdit, 
         Description = a.Description, 
         Views = a.Views, 
         Location = a.Location, 
         Photoshoot = a.Photoshoot, 
         Cover = (from ai in _imageRepository.Get() where ai.AlbumId == a.Id orderby ai.Cover descending, ai.Id ascending select ai).FirstOrDefault(), 
        }); 
    } 

最終,問題在於您試圖使用ActiveRecord模式而不是真正的存儲庫。需要通過相同的數據庫上下文實例來獲取單個IQueryable中的所有內容,以進行解析和跟蹤。

+0

我明白了,但是當我使用Linq2Sql劑量時它工作正常,並且它會自動檢測該關係並將其轉換爲左連接。實體框架是否簡單地沒有提前完成Linq2Sql中的功能? – Androme 2013-03-22 20:19:33

+0

我很驚訝地聽說L2S與單獨的存儲庫和上下文一起工作。你確定你沒有訪問a.AlbumImage而不是_imageRepository.Get嗎? L2S和EF確實有一些不同的語義,但我不會說它不夠先進。 – 2013-03-24 03:43:07

+0

您可以在OP – Androme 2013-03-24 16:44:35

1

潛在的,因爲你是在包裝新引用AlbumAlbumImage。我會刪除它,然後在之後執行投影

+0

我不明白你的意思? – Androme 2013-03-22 16:02:19

+0

@DoomStone不會執行'Get'中的'.Select'部分。 – 2013-03-22 16:05:10

+0

這將打敗使用存儲庫的整個理念 – Androme 2013-03-22 16:25:45

1

我不認爲你可以投影到一個實體,並讓每個投影使用另一個IQueryable的結果。如果更換的IQueryable<AlbumImage> Get()與此內容,它可能工作:

from a in _entities.Albums 
join c in _imageRepository.Get() on a.Id equals c.AlbumId into acJoin 
from ac in acJoin.DefaultIfEmpty() 
select new Album() 
{ 
    Id = a.Id, 
    etc.., 
    etc.., 
    Cover = ac 
} 

實際上,我相當肯定,你將需要調整這個寫意查詢,但本質上它加入IQueryables,然後突出的那些結果插入到對象中,而不是投影到對象,然後將IQueryable插入到這些結果中。不是我所知道的最好的解釋,只是查看「LINQ Left Join」或「Linq Left Outer Join」來查看我在這裏描述的語法的語法。 Example

+0

我剛剛對我的問題做了更新,Linq是否無法處理select中的新選擇?我知道Linq2sql輕鬆地處理這個問題嗎? – Androme 2013-03-22 16:49:28

+0

EF故意禁止許多允許實體和對象查詢之間混淆的查詢。如果* did *在Linq-to-SQL中工作,它可能會導致一個n + 1查詢,其中每個子查詢將單獨執行。你當然可以選擇數據的子集,但是你需要這樣做,它會知道如何獲得所有的查詢信息。 – Ocelot20 2013-03-22 16:54:48

+0

在對問題的更新中,新查詢仍會重複EF遇到問題的部分。我敢打賭,如果你用'from _albumRepository.Get()。ToList()'替換了_albumRepository.Get()'中的''它會起作用。注意:這不是您應該做的最終解決方案,但希望能夠澄清問題所在。 – Ocelot20 2013-03-22 16:59:35

相關問題