2013-03-22 63 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

相关问题