2013-08-02 20 views
8

Tôi cực kỳ mới với linq và khung pháp nhân. Tôi đang cố gắng giải quyết một vấn đề là tại sao bên dưới không hoạt động. Lỗi được tạo ra là "Không thể tạo ra một giá trị không đổi của kiểu 'Kiểu ẩn danh'. Chỉ có các kiểu nguyên thủy hoặc kiểu liệt kê mới được hỗ trợ trong ngữ cảnh này."Không thể tạo giá trị không đổi của loại 'Kiểu ẩn danh'. Chỉ các loại nguyên thủy hoặc kiểu liệt kê mới được hỗ trợ trong ngữ cảnh này

Tôi đã thử quá nhiều cách khác nhau nhưng vẫn gặp lỗi liên quan đến các kiểu nguyên thủy. Tôi sẽ đánh giá rất cao nếu ai đó có thể xem xét mã dưới đây và hy vọng chỉ ra nơi nó đang đi sai.

 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(); 
     } 
    } 

CẬP NHẬT

Tôi đã thực hiện một cách tiếp cận khác nhau với này ngay bây giờ bằng cách tạo ra một cái nhìn vì vậy tôi không còn cần phải làm bối cảnh xuyên tham gia trong EF. Tôi đã hy vọng bạn có thể giúp đỡ với bên dưới.

Khi tôi chạy objectQuery.ToTraceString() nó cung cấp cho tôi SQL hợp lệ trả về các bản ghi trong db, tuy nhiên resLst trong EntityFramework luôn quay trở lại với 0. Có điều gì rõ ràng là tại sao điều này xảy ra không?

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

Để cập nhật, tôi khuyên bạn nên sử dụng [Sql Server Profiler] (htt p: //msdn.microsoft.com/en-us/library/ms181091.aspx) và chụp sql mà EF thực sự đang gửi đến máy chủ. –

+0

Chúc mừng bạn đời. Sự cố chuỗi kết nối ngớ ngẩn. Bạn sống và học :-) – JIbber4568

Trả lời

5

Sự cố là cuộc gọi ToList() chi tiết. Trong EF, bạn chỉ có thể tham khảo một IEnumerable bên trong một truy vấn nếu IEnumerable là một kiểu đơn giản (e. G. Int). Tuy nhiên, bạn có thể tham khảo một IQueryable khác. Do đó, bỏ cuộc gọi ToList() nên thực hiện công việc này.

EDIT: tương tự, bạn nên thả lệnh ToList() trên ctx.CompanySettings.

này sẽ có những lợi thế nhất của thi chỉ có 1 truy vấn thay vì 2. Nếu bạn thả ToList() trên chi tiết, EF sẽ tạo ra một cái gì đó như:

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: để làm điều này qua những bối cảnh, bạn sẽ cần phải đưa truy vấn vào bộ nhớ (ví dụ bằng cách gọi AsEnumerable() và thực hiện các phép nối có liên quan ở đó Nếu các phép nối hoạt động như các bộ lọc và điều quan trọng là các bộ lọc này xảy ra trong SQL, hãy xem xét sử dụng Contains() Ví dụ:

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

Cảm ơn vì điều đó. Lý do nó được thực hiện như thế là chúng ta phải tham gia vào bối cảnh chéo. Theo như tôi biết mà không có .ToList(), chúng tôi không thể truy vấn ngữ cảnh chéo. Có cách tiếp cận khác với điều này tôi có lẽ nên dùng để cho phép tham gia bối cảnh chéo không? – JIbber4568

+0

@ JIbber4568 để tham gia qua bối cảnh, bạn cần phải kéo toàn bộ bảng cài đặt của công ty vào bộ nhớ và lọc bằng WHERE IN() (Chứa trong EF). – ChaseMedallion

+0

Cảm ơn sự giúp đỡ của bạn với điều này. Tôi đã thực hiện một cách tiếp cận hơi khác với điều này nhưng bây giờ có vấn đề với Entity Framework kế thừa các kết quả từ DB. Có điều gì rõ ràng trong bản cập nhật ở trên có thể gây ra điều này không? Cảm ơn – JIbber4568

Các vấn đề liên quan