2009-09-02 8 views
6

Mam model na szczycie mojego modelu bazy danych i odwzorowuję obiekty w moim repozytorium.Jak używać klas fabrycznych z linq dla sql?

Jednak najwyraźniej robi różnicę, czy "wybieram nowy" bezpośrednio w moich GetUsers lub "wybierz fabrykę" jak zaimplementowano poniżej. Otrzymuję błąd w czasie wykonywania, że ​​metoda CreateFromDbModel nie ma tłumaczenia na sql (System.NotSupportedException).

Czy istnieje sposób obejścia tego? Czy mogę go jakoś naprawić?

Powodem chcąc użyć metody fabryki jest, że mogę instanciate obiektów gdzie indziej i chcesz zachować „kod mapowania” w jednym miejscu ...

Dzięki za wszelkie komentarze, Anders

public IQueryable<User> GetUsers(bool includeTeams) 
    { 
     return from u in _db.sc_Players 
       where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam)) 
       select UserFactory2.CreateFromDbModel(u); 
    } 


    public static User CreateFromDbModel(sc_Player player) 
    { 
     return new User 
        { 
         Id = player.sc_PlayerID, 
         FirstName = player.FirstName.Trim(), 
         LastName = player.LastName.Trim(), 
         PresentationName = player.FirstName.Trim() + " " + player.LastName.Trim(), 
         LoginName = player.aspnet_User.LoweredUserName, 
         IsTeam = player.IsTeam, 
         Email = player.aspnet_User.aspnet_Membership.Email, 
         Password = player.aspnet_User.aspnet_Membership.Password 
        }; 
    } 

Odpowiedz

1

Czy problem polega na zwrocie IQueryable w metodzie GetUsers? Zamiast tego spróbuj zwrócić listę. Zmusi to zapytanie Linq do wykonania w ramach metody.

public List<User> GetUsers(bool includeTeams) 
{ 
    return (from u in _db.sc_Players 
    where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam)) 
    select UserFactory2.CreateFromDbModel(u)).ToList(); 
} 

Nie jestem pewien, czy to rozwiąże problem, tylko przeczucie. Byłem w stanie powielić to, co robisz w Linqpad na lokalnej bazie danych, i zadziałało. Ale moja próbka nie zwróciła IQueryable. Czy modyfikujesz kolekcję IQueryable poza GetUsers()?

Edit:

Zrobiłem kilka kontroli. I był w stanie odtworzyć tylko błąd, kiedy zmodyfikowane moje próbki więc zbiór IQueryable użyto w drugim kwerendy LINQ po wywołaniu GetUsers():

IQueryable<User> query = GetUsers(true); 

var q = from u in query 
    where u.Name.Contains("Bob") 
    select new {Name = u.FirstName + " " + u.LastName}; 

założę jeśli wrócisz listy jak zasugerowano powyżej w GetUsers() błąd zniknie. Jedyną wadą jest to, że każde filtrowanie wykonywane po wywołaniu funkcji GetUsers() nie ograniczy ilości danych zwracanych z bazy danych, ponieważ wykonano już zapytanie podczas wywoływania funkcji .ToList().

Edit 2:

Niestety nie sądzę, istnieje inny sposób na swój sposób fabryka w zapytaniu. Mam jeszcze jeden pomysł. Możesz utworzyć metodę rozszerzenia dla IQueryable, nazwij ją czymś takim jak ToUserList(). Wewnątrz ToUserList() wywołuje się ToList() w zapytaniu i fabrycznej metodzie, która zwraca kolekcję użytkowników. Wywołaj tę metodę po zakończeniu filtrowania danych za pomocą Linq. Umożliwi to wykonanie zapytania tylko wtedy, gdy będziesz gotowy do załadowania danych z bazy danych. Przykład podano poniżej.

public static List<Users> ToUserList(this IQueryable<User> query) 
{ 
    return query.ToList().Select(u => UserFactory2.CreateFromDbModel(u)); 
} 

wywołać metodę rozszerzenie tak:

// Filter the data using linq. When you are ready to execute the query call: 
query.ToUserList(); // Query will execute and a list of User objects returned. 

Nadzieja to sens. Douglas H.

+0

Dzięki Douglas i Rossisdead, próbowałem konwersji do listy przed wywołaniem moje metody fabryki, ale nie tylko muszę wrócić cały LINQ obiektów z bazy danych, muszę również zbudować wszystkie moje obiekty modelu domeny - i próbowałem znaleźć sposób, który nie wymagał ... Ponadto dokonuję filtrowania w mojej warstwie usługi i będę musiał przekonwertować listę z powrotem na zapytanie. ... –

+0

Witam Anders, Zobacz Edytuj 2 powyżej. – Douglas

+0

Witaj, Douglas, Oznaczam twoją odpowiedź jako odpowiedź, ale miałem nadzieję, że utrzymam obiekty linq bazy danych w warstwie danych, w której Twoja sugestia wystawiłaby obiekty warstwy danych na warstwę usługi. –

1

Błąd prawie wszystko tłumaczy.

"metoda CreateFromDbModel nie ma tłumaczenia na sql (System.NotSupportedException) "

Twoja metoda CreateFromDbModel nie jest funkcją sql. Twoja aplikacja nie będzie mogła uruchomić funkcji CreateFromDbModel, dopóki obiekty nie zostaną specjalnie zwrócone do ciebie z serwera. Najprawdopodobniej będziesz musiał wywołać ToList() lub coś podobnego na zapytaniu, zanim będzie można uruchomić CreateFromDbModel na nich.