2013-08-02 15 views
8

Jestem niezmiernie nowy dla linq i struktury encji. Próbuję rozwiązać problem, dlaczego poniżej nie działa. Powstały błąd to "Nie można utworzyć stałej wartości typu" Typ anonimowy ". W tym kontekście obsługiwane są tylko typy pierwotne lub typy wyliczeniowe."Nie można utworzyć stałej wartości typu "Typ anonimowy". W tym kontekście obsługiwane są tylko prymitywne typy lub typy wyliczeniowe.

Próbowałem już na tak wiele różnych sposobów, ale wciąż pojawia się błąd związany z typami pierwotnymi. Byłbym bardzo wdzięczny, gdyby ktoś mógł rzucić okiem na poniższy kod i mam nadzieję, że wskaże, gdzie jest źle.

 public Entities.BikeData[] GetBikesWithExpiredSyncDeadline(int noOfDays) { 

     using (OfficeEntities cxt = GetContext()) 
     using (ReportingEntities RepCxt = GetReportingContext()) { 
      Data.Repository.Abstract.IBikeRepository BikeRepos = new Data.Repository.Concrete.BikeRepository();     

      var details = (from sd in cxt.BikeDetails 
             where sd.autoreminder == true 
              && (sd.lastremindersent == null || sd.lastremindersent < EntityFunctions.AddDays(DateTime.UtcNow, noOfDays * -1)) 
              && (sd.emailaddress != null && sd.emailaddress.Trim() != "") 
             select new { 
              Serial = sd.Serial, 
              EmailAddress = sd.emailaddress 
             }).ToList(); 

      var resLst = (from r in RepCxt.RegisteredBikes 
          join d in details on r.Serial equals d.Serial 
          join cs in cxt.CompanySettings.ToList() on r.CompanyID equals cs.CompanyID 
          where (!r.lastupdate.HasValue || r.lastupdate < EntityFunctions.AddDays(DateTime.UtcNow, cs.AutoNotificationFrequency * -1)) 
          select new Entities.BikeData { 
           ID = r.ID, 
           Name = r.Ship, 
           Serial = r.Serial, 
           LastUpdate = r.lastupdate, 
           DaysSinceLastSync = (r.lastupdate.HasValue? EntityFunctions.DiffDays(r.lastupdate.Value, DateTime.UtcNow).Value : -1), 
           EmailAddress = (d.EmailAddress == null ? string.Empty : (String.IsNullOrEmpty(d.EmailAddress) ? r.ShipEmailAddress : d.EmailAddress)) 
          }); 

      return resLst.ToArray(); 
     } 
    } 

UPDATE

Wziąłem innego podejścia z tym teraz, tworząc widok, więc nie trzeba już robić krzyż kontekst łączy w EF. Miałem nadzieję, że możesz pomóc z poniższymi.

Po uruchomieniu obiektu objectQuery.ToTraceString() zapewnia on poprawny kod SQL, który zwraca rekordy w db, jednak resLst w EntityFramework zawsze zwraca wartość 0. Czy jest coś oczywistego, dlaczego tak się dzieje?

var resLst = (from ls in cxt.BikeLastUpdates 
          where (!ls.lastupdate.HasValue || ls.lastupdate < EntityFunctions.AddDays(DateTime.UtcNow, ls.AutoNotificationFrequency * -1)) 
          && (ls.autoreminder ==true) 
          && (ls.lastremindersent == null || ls.lastremindersent < EntityFunctions.AddDays(DateTime.UtcNow, 3 * -1)) 
          && (ls.emailaddress !=null && ls.emailaddress.Trim() != "") 
          select new Entities.BikeData{ 
           ID = (ls.ID ?? new Guid()), 
           Name = ls.Bike, 
           Serial = ls.Serial, 
           LastUpdate = ls.lastupdate, 
           EmailAddress = (String.IsNullOrEmpty(ls.emailaddress) ? ls.ShipEmailAddress : ls.emailaddress) 
          }); 

      var objectQuery = resLst as ObjectQuery; 

      return resLst.ToArray(); 
+0

Dla twojej aktualizacji polecam używanie [Sql Server Profiler] (htt p: //msdn.microsoft.com/en-us/library/ms181091.aspx) i przechwytywanie sql, który EF faktycznie wysyła na serwer. –

+0

Pozdrawiam kumpla. Głupi problem z łańcuchem połączeń. Żyjesz i uczysz się :-) – JIbber4568

Odpowiedz

5

Problem polega na wywołaniu funkcji ToList(). W EF, możesz odwoływać się tylko do IEnumerable wewnątrz zapytania, jeśli IEnumerable jest prostego typu (np. Int). Możesz jednak odwołać się do innego IQueryable. Dlatego upuszczenie wywołania ToList() powinno sprawić, że to zadziała.

EDYCJA: podobnie, powinieneś upuścić wywołanie ToList() na ctx.CompanySettings.

To będzie mieć dodatkową zaletę wykonanie tylko 1 zapytanie zamiast 2. W przypadku upuszczenia ToList() na szczegółach, EF wygeneruje coś takiego:

SELECT ... 
FROM RegisteredBikes rb 
JOIN (
    /* this is your "details" IQueryable */ 
    SELECT Serial, EmailAddress 
    FROM BikeDetails 
    WHERE ... 
) bd 
    ON rb.Serial = b.Serial 
JOIN CompanySettings cs 
    ON ... 
WHERE ... 

EDIT: to zrobić w poprzek kontekstach musisz wprowadzić kwerendę do pamięci (np. wywołując funkcję AsEnumerable()) i wykonać odpowiednie połączenia.Jeśli połączenia działają jak filtry i ważne jest, aby te pojawiły się w SQL, rozważ użycie Contains(). Na przykład:

var serials = details.Select(d => d.Serial); 
var filtered = RepCtxt.RegisteredBikes.Where(r => details.Contains(r.Serial); 
+0

Dzięki za to. Powodem tego jest to, że musimy połączyć kontekst krzyżowy. O ile jestem świadomy bez .ToList(), nie jesteśmy w stanie przetworzyć kontekstu krzyżowego. Czy istnieje inne podejście do tego, które powinienem brać, aby umożliwić łączenie kontekstowe? – JIbber4568

+0

@ JIbber4568 w celu dołączenia do kontekstu krzyżowego, należy pobrać całą tabelę ustawień przedsiębiorstwa do pamięci i przefiltrować za pomocą WHERE IN() (Zawiera w EF). – ChaseMedallion

+0

Dziękujemy za pomoc w tej sprawie. Podjąłem z tym nieco inne podejście, ale mam teraz problemy z Entity Framework dziedzicząc wyniki z DB. Czy jest coś oczywistego w powyższej aktualizacji, które może być przyczyną tego? Dzięki – JIbber4568

Powiązane problemy