Linq to SQL с использованием шаблона репозитория: у объекта нет поддерживаемого перевода в SQL - PullRequest
2 голосов
/ 03 августа 2010

Я все это время чесал голову за этим утром, но все еще не мог понять, что может быть причиной этого.

У меня есть составной объект репозитория, который ссылается на два других репозитория. Я пытаюсь создать экземпляр типа Model в своем запросе LINQ (см. Первый фрагмент кода).

public class SqlCommunityRepository : ICommunityRepository {</p> <pre><code> 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 {</p> <p>private WebDataContext _ctx;</p> <p>public SqlStateRepository(WebDataContext ctx) { _ctx = ctx; }</p> <pre><code> 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 {</p> <p>private WebDataContext _ctx;</p> <pre><code> 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 не может правильно построить дерево выражений?

Ответы [ 2 ]

1 голос
/ 03 августа 2010

Это не гидратированные запросы, а не полностью гидратированные коллекции.

Запрос Сообщества отличается от двух других тем, что он вызывает методы , поскольку объекты гидратируются.Эти вызовы методов не могут быть переведены в SQL.


Обычно это не проблема.Например: если вы скажете Communities.ToList (), он будет работать, и методы будут вызываться из объектов по мере их гидратации.

Если вы измените запрос так, что объекты не будутгидратированный , например: когда вы говорите Communities.Count (), linq to sql пытается отправить вызовы метода в базу данных и выбрасывает, поскольку это невозможно.Он делает это, даже несмотря на то, что эти вызовы методов, в конечном счете, не повлияют на итоговое число.


Самое простое исправление (если вы действительно ожидаете полностью гидратированные коллекции) - добавить ToList к запросу сообщества, увлажняя его.

0 голосов
/ 03 августа 2010

Попробуйте добавить другой метод репозитория, который выглядит следующим образом:

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

Это позволит вам возвращать счетчик, не выставляя пользователю все дерево объектов, как я думаю, вы пытаетесьделать в любом случае.

Как вы, возможно, уже догадались, я подозреваю, что виноваты в том, что вы называете анонимными типами (на самом деле это не анонимные типы; они являются реальными объектами, которые, по-видимому, частично заполненыпопытка скрыть некоторые поля от конечного пользователя).

...