2

我一直在这个背后摸不着头脑,但仍然无法弄清楚可能会导致这种情况。Linq to SQL使用存储库模式:对象没有支持转换到SQL

我有一个复合存储库对象引用两个其他存储库。我想在我的LINQ查询中实例化Model类型(请参阅第一个代码片段)。

public class SqlCommunityRepository : ICommunityRepository {

private WebDataContext _ctx; 
    private IMarketRepository _marketRepository; 
    private IStateRepository _stateRepository; 

    public SqlCommunityRepository(WebDataContext ctx, IStateRepository stateRepository, IMarketRepository marketRepository) 
    { 
     _ctx = ctx; 
     _stateRepository = stateRepository; 
     _marketRepository = marketRepository; 
    } 

    public IQueryable<Model.Community> Communities 
    { 
     get 
     { 
      return (from comm in _ctx.Communities 
        select new Model.Community 
        { 
         CommunityId = comm.CommunityId, 
         CommunityName = comm.CommunityName, 
         City = comm.City, 
         PostalCode = comm.PostalCode, 
         Market = _marketRepository.GetMarket(comm.MarketId), 
         State = _stateRepository.GetState(comm.State) 
        } 
        ); 
     } 
    } 
} 

说我传递模样的资源库对象本

public class SqlStateRepository : IStateRepository {

private WebDataContext _ctx;

public SqlStateRepository(WebDataContext ctx) { _ctx = ctx; }

public IQueryable<Model.State> States 
    { 
     get 
     { 
      return from state in _ctx.States 
        select new Model.State() 
        { 
         StateId = state.StateId, 
         StateName = state.StateName 
        }; 
     } 
    } 

    public Model.State GetState(string stateName) 
    { 
     var s = (from state in States 
       where state.StateName.ToLower() == stateName 
       select state).FirstOrDefault(); 

     return new Model.State() 
     { 
      StateId = s.StateId, 
      StateName = s.StateName 
     }; 
    } 

public class SqlMarketRepository : IMarketRepository {

private WebDataContext _ctx;

public SqlMarketRepository(WebDataContext ctx) 
    { 
     _ctx = ctx; 
    } 

    public IQueryable<Model.Market> Markets 
    { 
     get 
     { 
      return from market in _ctx.Markets 
        select new Model.Market() 
           { 
            MarketId = market.MarketId, 
            MarketName = market.MarketName, 
            StateId = market.StateId 
           }; 
     } 
    } 

    public Model.Market GetMarket(int marketId) 
    { 
     return (from market in Markets 
       where market.MarketId == marketId 
       select market).FirstOrDefault(); 
    } 
} 

这是我如何接线这一切:

 WebDataContext ctx = new WebDataContext(); 
     IMarketRepository mr = new SqlMarketRepository(ctx); 
     IStateRepository sr = new SqlStateRepository(ctx); 
     ICommunityRepository cr = new SqlCommunityRepository(ctx, sr, mr); 
     int commCount = cr.Communities.Count(); 

上面代码片段的最后一行是失败的地方。当我通过实例化(new Model.Community)进行调试时,它永远不会进入任何其他存储库方法。这三个对象背后的底层表之间没有关系。这是否会成为LINQ to SQL无法正确构建表达式树的原因?

回答

1

这些是非水合查询,而不是完全水合的集合。

社区查询与其他两个查询不同,因为在对象水合时调用方法。这些方法调用不能转换为SQL。


通常这不是问题。例如:如果你说Communities.ToList(),它将起作用,并且方法将在对象水合时被调用。

如果修改查询,以便的对象不水合,例如:当你说Communities.Count(),LINQ to SQL中尝试发送方法调用到数据库中,并抛出,因为它不能。即使这些方法调用最终不会影响结果计数,它也会这样做。


的简单的解决办法(如果你真正希望完全水化的集合)是添加ToList到社区查询,补水吧。

+0

这样做。它不会触发查询,直到你调用IQueryable上的方法? – Praveen 2010-08-03 18:30:51

+1

大多数Linq方法都是延迟的 - 直到枚举结果才会评估查询。 foreach和ToList都是枚举查询的手段。 – 2010-08-03 23:13:19

0

尝试增加看起来像这样的另一个仓库方法:

public int CommunitiesCount() 
{ 
    get { return _ctx.Communities.Count(); } 
} 

这将允许您无需将整个对象树暴露给用户,这是我认为你正在试图做的返回计数无论如何。你可能已经猜到了,我怀疑你所称的匿名类型是错误的(它们并不是真正的匿名类型,它们是实际的对象,你显然是为了隐藏某些东西来自最终用户的字段)。

+0

我不确定Count()方法本身是否是罪魁祸首。当我做cr.Communities时,我期待着一个完全水合的IQueryable集合。 mr.Markets.Count()和sr.States.Count()返回预期的结果。 – Praveen 2010-08-03 00:09:28

+0

count()的这个特殊的演绎是否奏效? – 2010-08-03 01:03:19

+0

是的,_ctx.Communities.Count()给我正确的计数。但是,我正在寻找communityRepository.Communities,一个IQueryable 列表。 – Praveen 2010-08-03 15:29:16