トップ回答者
LINQのSELECTの全項目と指定項目の違いについて

質問
-
LINQのSELECTの全項目はエラーにならず、
項目指定の場合
型 'System.Collections.Generic.List`1[VB$AnonymousType_0`6[System.Int32,System.String,System.DateTime,System.String,System.Decimal,System.String]]'
のオブジェクトを型 'System.Collections.Generic.IEnumerable`1[MvcMovie.Movie]' にキャストできません。のエラーになってしまいます。
LINQのSELECTの全項目の場合(エラーにならない)
Dim movies = From m In db.Movies
Select m
md.Mymo = movies.ToList()<---モデルクラスへ設定LINQのSELECTの項目指定の場合(エラーになる)
Dim movies = From m In db.Movies
Select m.ID, m.Title, m.ReleaseDate, m.Genre, m.Price, m.Rating
md.Mymo = movies.ToList()<---モデルクラスへ設定(エラーになってしまう)DBのテーブル項目内容
Public Class Movie
Public Property ID() As Integer<Required()>
Public Property Title() As StringPublic Property ReleaseDate() As Date
Public Property Genre() As String
<Required(), Range(5, 100, ErrorMessage:="The price must be between $5 and $100")>
Public Property Price() As Decimal<StringLength(5)>
Public Property Rating() As String
End Classモデルクラス
Public Class Mymodel
Public Property Mymo() As IList(Of Movie)
End Class何故SELECTで全項目の時はエラーにならず、指定項目の時はキャストできませんエラーになるのでしょうか?
回答
-
返信ありがとうございます。
Public Class Mymodel
Public Property Mymo() As IList(Of Movie)
End Class↓修正(Movie 型のインスタンス作成は今回はしないことにしましたが、対処方法としてはMovie 型のインスタンス作成と
言うことですね。(List<Movie> にしたければ、 New Movie With {} を使って Movie 型のインスタンスを作ってください。)
Public Class Mymodel
Public Property Mymo() As IList
End Classありがとうございました。
- 回答としてマーク winwin333 2011年8月15日 9:13
-
返信ありがとうございます。
項目指定時は、Movie() クラスへDB項目を設定した方がデータ型が設定されるということですね。ありがとうございました。
Dim movies = From m In db.Movies
Select New Movie() With {
.ID = m.ID,
.Title = m.Title,
.ReleaseDate = m.ReleaseDate,
.Genre = m.Genre,
.Price = m.Price,
.Rating = m.Rating }
md.Mymo = movies.ToList()
Microsoft SQL Server データ型と、それぞれに対応する System.Data.SqlTypes 名前空間の SQL Server CLR (共通言語ランタイム) データ型および Microsoft .NET Framework のネイティブ CLR データ型を示します。
http://msdn.microsoft.com/ja-jp/library/ms131092(v=sql.90).aspx- 回答としてマーク winwin333 2011年8月15日 11:16
すべての返信
-
エラーメッセージを見ると、匿名型のリストを Movie のリストに代入しようとしているため例外が発生しています。クエリは匿名型のリストを生成してます。
成功するクエリは From m In db.Movies Select m としてるので、推測するに m は Movie 型のインスタンスであり、それをそのまま Select で返却しているからエラーにならないのでしょう。対処法としては、Select 句で Movie のコンストラクタを改造し、インスタンスを生成して返却するか、もしくは Mymodel の Mymo プロパティを IList(Of Movie) から IList のみにして対応する方法が考えられます。個人的には IList にするのが好きですね。
Public Class Mymodel Public Property Mymo() As IList End Class
ひらぽん http://d.hatena.ne.jp/hilapon/
- 編集済み ひらぽんModerator 2011年8月15日 10:04
-
もし Mymodel クラスのプロパティを変更できないなら、以下のように Movie クラスのコンストラクタを改造し、Select 句の中で Movie のインスタンスを生成します。
Public Class Movie Public Property ID() As Integer <Required()> Public Property Title() As String Public Property ReleaseDate() As Date Public Property Genre() As String <Required(), Range(5, 100, ErrorMessage:="The price must be between $5 and $100")> Public Property Price() As Decimal <StringLength(5)> Public Property Rating() As String Public Sub New() End Sub Public Sub New (id As Integer, title As String, releaseDate As Date, genre As String, price AS Decimal, rating As String) Me.ID = id Me.Title = title Me.ReleaseDate = releaseDate Me.Genre = genre Me.Price = price Me.Rating = rating End Sub End Class Dim movies = From m In db.Movies Select New Movie(m.ID, m.Title, m.ReleaseDate, m.Genre, m.Price, m.Rating) md.Mymo = movies.ToList()
ひらぽん http://d.hatena.ne.jp/hilapon/ -
返信ありがとうございます。
Public Class Mymodel
Public Property Mymo() As IList(Of Movie)
End Class↓修正(Movie 型のインスタンス作成は今回はしないことにしましたが、対処方法としてはMovie 型のインスタンス作成と
言うことですね。(List<Movie> にしたければ、 New Movie With {} を使って Movie 型のインスタンスを作ってください。)
Public Class Mymodel
Public Property Mymo() As IList
End Classありがとうございました。
- 回答としてマーク winwin333 2011年8月15日 9:13
-
解決済みのようですが、某所で指摘されました。わざわざコンストラクタ用意せず、オブジェクト初期化子で返す方法もありましたね。orz
Dim movies = From m In db.Movies Select New Movie() With { .ID = m.ID, .Title = m.Title, .ReleaseDate = m.ReleaseDate, .Genre = m.Genre, .Price = m.Price, .Rating = m.Rating } md.Mymo = movies.ToList()
あと IList のジェネリック指定しないのも非推奨と指摘されてます。これについてはまだ調べてます。
ひらぽん http://d.hatena.ne.jp/hilapon/
- 編集済み ひらぽんModerator 2011年8月15日 9:25 コードの修正
-
すみません。更新が遅れて iwanaga さんの発言が読めてませんでした。
後者の書き方の、
Select m.ID, m.Title, m.ReleaseDate, m.Genre, m.Price, m.Rating
の場合、これは、ID, Title, ReleaseDate, Genre, Price, Rating というプロパティを持つ新しい匿名型が作られます。元の方(Movie クラス)にはなりません。
List<Movie> にしたければ、 New Movie With {} を使って Movie 型のインスタンスを作ってください。
IWANAGA Nobuyuki
この回答が最良の対処法だと思えます。Public Property Mymo() As IList としてジェネリックを外すのは型の安全性から返って非推奨との意見が何人かの方から上がっております。私がガイドラインを誤って捉えていたようです。誤った情報を提供してすみません。 IList(Of Movie) → IList は忘れてください。
ひらぽん http://d.hatena.ne.jp/hilapon/ -
返信ありがとうございます。
項目指定時は、Movie() クラスへDB項目を設定した方がデータ型が設定されるということですね。ありがとうございました。
Dim movies = From m In db.Movies
Select New Movie() With {
.ID = m.ID,
.Title = m.Title,
.ReleaseDate = m.ReleaseDate,
.Genre = m.Genre,
.Price = m.Price,
.Rating = m.Rating }
md.Mymo = movies.ToList()
Microsoft SQL Server データ型と、それぞれに対応する System.Data.SqlTypes 名前空間の SQL Server CLR (共通言語ランタイム) データ型および Microsoft .NET Framework のネイティブ CLR データ型を示します。
http://msdn.microsoft.com/ja-jp/library/ms131092(v=sql.90).aspx- 回答としてマーク winwin333 2011年8月15日 11:16