iT邦幫忙

0

Lambda+Join語法DataType問題

  • 分享至 

  • xImage

各位先進好,小弟ASP.NET MVC + Lambda初心者,上來求教,可能會有很多用詞、標題與描述沒有那麼的到位或詳細,請各位見諒~
問題:
目前剛規劃一個新專案,寫好一個資料表MVC相關程式碼,在搜尋單一資料表Conference的功能測試沒問題,如下程式碼,將資料由DB撈出來並在View裡呈現,測試是沒問題的。

SubmissionEntities db = new SubmissionEntities();
        private IQueryable<Conference> GetAllGetConferenceDataList(ForPaging Paging, string Search)
        {
            //根據搜尋值來搜尋資料
            IQueryable<Conference> Data = db.Conferences.Where(c => 
            //計算所需的總頁數
            Paging.MaxPage = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Data.Count()) / Paging.ItemNum));
            Paging.testNum = Data.Count();
            //Paging.MaxPage = 6;
            //重新設定正確的頁數,避免有不正確值傳入
            Paging.SetRightPage();
            //回傳搜尋資料
            return Data;
        }

因為資料表關聯的問題,所以要修改以上程式碼,加入Join MemberToConferences資料表的判斷,修改如下:

SubmissionEntities db = new SubmissionEntities();
        private IQueryable<Conference> GetAllGetConferenceDataList(ForPaging Paging, string Search)
        {
            //根據搜尋值來搜尋資料
            IQueryable<Conference> Data = db.Conferences.Join(db.MemberToConferences,
                c => c.ConferenceId,
                mc => mc.ConferenceId,
                (c, mc) => new
                {
                    ConferenceId = c.ConferenceId,
                    ConferenceTitle = c.ConferenceTitle,
                    ConferenceLocation = c.ConferenceLocation,
                    ContactName = c.ContactName
                }).OrderBy(c => c.ConferenceId).Where(c => c.ConferenceTitle.Contains(Search) || c.ConferenceLocation.Contains(Search) || c.ContactName.Contains(Search));
            //計算所需的總頁數
            Paging.MaxPage = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Data.Count()) / Paging.ItemNum));
            Paging.testNum = Data.Count();
            //Paging.MaxPage = 6;
            //重新設定正確的頁數,避免有不正確值傳入
            Paging.SetRightPage();
            //回傳搜尋資料
            return Data;
        }

VS就指出發生型別錯誤,應該是指以上程式碼撈出來的資料並非為IQueryable型態,需要轉型,目前我對Join其它資料表的程式撰寫不熟,所以不知道該如何修正以上這個需求,故上來請教。
採用DB First + EF + ViewModel方式開發,如有需要其它資訊我再補上,大感謝各位先進指教了,謝謝~

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

2
暐翰
iT邦大師 1 級 ‧ 2019-05-15 22:45:01
最佳解答


回復新問題:

LINQ to Entities 查詢中無法建構實體或複雜類型 'SubmissionModel.Conference'。
描述: 在執行目前 Web 要求的過程中發生未處理的例外狀況。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。

例外狀況詳細資訊: System.NotSupportedException: LINQ to Entities 查詢中無法建構實體或複雜類型 'SubmissionModel.Conference'。

麻煩看一下圖片,主要你在new Conference動作時,代表建立沒有資料庫效果的Conference物件

改成這樣就可以


回復新問題2:

LINQ to Entities 無法辨識方法 'Int32 ToInt32(System.Object)' 方法,而且這個方法無法轉譯成存放區運算式。
描述: 在執行目前 Web 要求的過程中發生未處理的例外狀況。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。

LINQ 能跟資料庫互動是因為有解釋器轉成SQL,對解釋器來說不認得ToInt32方法
所以我們可以改成LINQ一定認得的`『值』``,改寫成下面Code

var memberId = Convert.ToInt32(HttpContext.Current.Session["MemberId"];
IQueryable<Conference> Data = db.Conferences.Where(c => c.Enabled == true)
    .Join(db.MemberToConferences.Where(mc => mc.MemberId == memberId)),
    c => c.ConferenceId,
    mc => mc.ConferenceId,
    (c, mc) => c);
看更多先前的回應...收起先前的回應...
leo226 iT邦新手 4 級 ‧ 2019-05-16 12:23:07 檢舉

謝謝指正,我修改程式碼如下:

        private IQueryable<Conference> GetAllGetConferenceDataList(ForPaging Paging)
        {
            //宣告要回傳的搜尋資料為資料庫中的Guestbooks資料表
            //IQueryable<Conference> Data = db.Conferences.Where(c => c.Enabled == true);
            IQueryable<Conference> Data = db.Conferences.Join(db.MemberToConferences.Where(mc => mc.MemberId == 5),
                c => c.ConferenceId,
                mc => mc.ConferenceId,
                (c, mc) => new Conference
                {
                    ConferenceId = c.ConferenceId,
                    ConferenceTitle = c.ConferenceTitle,
                    ConferenceLocation = c.ConferenceLocation,
                    ContactName = c.ContactName
                })
            .Where(c => c.Enabled == true);

            //計算所需的總頁數
            //Paging.MaxPage = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Data.Count()) / Paging.ItemNum));
            Paging.MaxPage = 6;
            //重新設定正確的頁數,避免有不正確值傳入
            Paging.SetRightPage();
            //回傳搜尋資料
            return Data;
        }

接著遇到其它錯誤

LINQ to Entities 查詢中無法建構實體或複雜類型 'SubmissionModel.Conference'。
描述: 在執行目前 Web 要求的過程中發生未處理的例外狀況。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。 

例外狀況詳細資訊: System.NotSupportedException: LINQ to Entities 查詢中無法建構實體或複雜類型 'SubmissionModel.Conference'。

原始程式錯誤: 


行 89: 
行 90:             //計算所需的總頁數
行 91:             Paging.MaxPage = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Data.Count()) / Paging.ItemNum));
行 92:             //Paging.MaxPage = 6;
行 93:             //重新設定正確的頁數,避免有不正確值傳入

若把Paging.MaxPage = 6;寫死試著跳過此錯誤,到呼叫此方法的函式還是再報類似的錯誤,程式碼及錯誤如下:
呼叫GetAllGetConferenceDataList(Paging)的主函式

        public List<Conference> GetConferenceDataList(ForPaging Paging, string Search)
        {
            //宣告要接受全部搜尋資料的物件
            IQueryable<Conference> SearchData;
            //判斷搜尋是否為空或Null,用於決定要呼叫取得搜尋資料
            if (String.IsNullOrEmpty(Search))
            {
                SearchData = GetAllGetConferenceDataList(Paging);
            }
            else
            {
                SearchData = GetAllGetConferenceDataList(Paging, Search);
            }
            //先排序再根據分頁來回傳所需部份的資料陣列
            return SearchData.OrderByDescending(c => c.ConferenceId).Skip((Paging.NowPage - 1) * Paging.ItemNum).Take(Paging.ItemNum).ToList();
        }

以下依然報錯

LINQ to Entities 查詢中無法建構實體或複雜類型 'SubmissionModel.Conference'。
描述: 在執行目前 Web 要求的過程中發生未處理的例外狀況。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。 

例外狀況詳細資訊: System.NotSupportedException: LINQ to Entities 查詢中無法建構實體或複雜類型 'SubmissionModel.Conference'。

原始程式錯誤: 


行 44:             }
行 45:             //先排序再根據分頁來回傳所需部份的資料陣列
行 46:             return SearchData.OrderByDescending(c => c.ConferenceId).Skip((Paging.NowPage - 1) * Paging.ItemNum).Take(Paging.ItemNum).ToList();
行 47:         }
行 48:         //包含搜尋值的搜尋資料方法

現在不懂的是,以下A,B兩個寫法回傳都是同樣型別,為何A可以順利執行,B卻無法呢?
A寫法

IQueryable<Conference> Data = db.Conferences.Where(c => c.Enabled == true);

B寫法,加入Join

IQueryable<Conference> Data = db.Conferences.Join(db.MemberToConferences.Where(mc => mc.MemberId == 5),
                c => c.ConferenceId,
                mc => mc.ConferenceId,
                (c, mc) => new Conference
                {
                    ConferenceId = c.ConferenceId,
                    ConferenceTitle = c.ConferenceTitle,
                    ConferenceLocation = c.ConferenceLocation,
                    ContactName = c.ContactName
                })
            .Where(c => c.Enabled == true);

還是卡關,不知道該如何修正,如果有先進看到問題,再麻煩指正了,謝謝~
感謝暐翰的指教,謝謝

leo226 iT邦新手 4 級 ‧ 2019-05-16 14:49:09 檢舉

測試回覆,我將搜尋寫法改成如下LINQ語法,程式就可以正常執行了,但還是不知道問題在那裡!

            IQueryable<Conference> Data =
            (from c in db.Conferences
             join mc in db.MemberToConferences on c.ConferenceId equals mc.ConferenceId
             where c.Enabled == true
             select c);

雖然暫時解決問題可持續開發下去,但還是想知道上述造成問題的原因為何,如果有任何先進知道問題的還請麻煩指教一下了,大大感謝~

暐翰 iT邦大師 1 級 ‧ 2019-05-16 15:00:15 檢舉

_

暐翰 iT邦大師 1 級 ‧ 2019-05-16 15:09:20 檢舉

leo226 我更新回答在內文 你看一下

leo226 iT邦新手 4 級 ‧ 2019-05-16 15:39:18 檢舉

暐翰抱歉沒有注意上面有回文,感謝指教,依建議修改程式碼可正常運作~
想要再進一步請教延伸問題,搜尋條件想要再進一步帶入Session值為搜尋條件,修改成以下程式碼:

            IQueryable<Conference> Data = db.Conferences.Where(c => c.Enabled == true)
                .Join(db.MemberToConferences.Where(mc => mc.MemberId == Convert.ToInt32(HttpContext.Current.Session["MemberId"])),
                c => c.ConferenceId,
                mc => mc.ConferenceId,
                (c, mc) => c);

執行階段出現以下錯誤訊息,我想應該是Session值引用錯誤的問題造成,因為若將Session值改為固定值帶入則可正常運作。


LINQ to Entities 無法辨識方法 'Int32 ToInt32(System.Object)' 方法,而且這個方法無法轉譯成存放區運算式。
描述: 在執行目前 Web 要求的過程中發生未處理的例外狀況。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。 

例外狀況詳細資訊: System.NotSupportedException: LINQ to Entities 無法辨識方法 'Int32 ToInt32(System.Object)' 方法,而且這個方法無法轉譯成存放區運算式。

原始程式錯誤: 


行 90: 
行 91:             //計算所需的總頁數
行 92:             Paging.MaxPage = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Data.Count()) / Paging.ItemNum));
行 93:             //Paging.MaxPage = 6;
行 94:             //重新設定正確的頁數,避免有不正確值傳入

此Session["MemberId"]在View裡都可以正常的代出數值顯示,可是用在此搜尋類別檔裡卻會造成問題!
所以問題應該是我們應該如何在類別檔裡代入Session值使用呢?

不好意思,初心者遇到的問題有點多~謝謝幫忙~

暐翰 iT邦大師 1 級 ‧ 2019-05-16 16:02:32 檢舉

leo226 我更新回答了

leo226 iT邦新手 4 級 ‧ 2019-05-16 16:37:44 檢舉

暐翰觀念清楚許多,感謝不吝指教,謝謝~

0
小魚
iT邦大師 1 級 ‧ 2019-05-15 18:19:04

Join沒用過,
不過你把滑鼠移過去,
應該會看到Join回傳的類別,
而且通常錯誤訊息裡面應該也會寫...

我要發表回答

立即登入回答