2017-09-09 6 views
1

私は2つのモデル(Ninja & Dojo)を持​​っています。ViewBagの表示クラスのプロパティを作成するにはどうすればよいですか?

これらは1対多の関係です(NinjaはOne Dojoに属し、DojoはNinjasを多く持つことができます)。

私はDapperを使用しています。私は私のコントローラで

public IEnumerable<Ninja> FindAll() 
{ 
    using (IDbConnection dbConnection = Connection) 
    { 
     dbConnection.Open(); 
     return dbConnection.Query<Ninja>("SELECT * FROM ninjas"); 
    } 
} 

Dojo.cs

using System.ComponentModel.DataAnnotations; 
using System; 
using System.Collections.Generic; 

namespace dojoleague.Models { 
public class Dojo : BaseEntity{ 

    [Key] 
    public long Id {get; set;} 

    [Required] 
    public string Name {get; set;} 

    [Required(ErrorMessage="We have to know where it is")] 
    public string Location {get; set;} 

    [Required(ErrorMessage="Provide additional info on the Dojo")] 
    public string Description {get; set;} 

    public ICollection<Ninja> Ninjas { get; set; } 

} 
} 

Ninja.cs

using System.ComponentModel.DataAnnotations; 
using dojoleague.Models; 
using System; 

namespace dojoleague.Models { 
public class Ninja : BaseEntity{ 

    [Key] 
    public long Id {get; set;} 

    [Required(ErrorMessage="You need a name!")] 
    public string Name {get; set;} 

    [Range(1,11, ErrorMessage="Must be between 1 and 10")] 
    public int Level {get; set;} 

    [Required] 
    public Dojo Dojo {get; set;} 

    public string Description {get; set;} 


    } 
} 

Ninjafactory

ninjaFactory.Add(newNinja, dojo); 
System.Console.WriteLine(newNinja.Dojo.Name); 
ViewBag.Ninja = ninjaFactory.FindAll(); 
return View(); 

これで、System.Console.WriteLine(newNinja.Dojo.Name)は、コンソールにDojoの名前を正しく出力します。

ただし、WebブラウザにDojoの名前は表示されません。私CSHTMLで

@{ 
    foreach(var ninja in ViewBag.Ninja){ 
     <h2>@ninja.Name</h2> 
     <h4>@ninja.Dojo.Name</h4> 
    } 
} 

それは@ ninja.Nameを印刷んが、それは

RuntimeBinderExceptionを言っninja.Dojo.Name @プリントアウトしません:ヌルに実行時バインディングを実行できません参照

ViewBagを使用して、Ninjaクラスに属するDojoクラスの属性を作成するにはどうすればよいですか?

ありがとうございます。

+0

あなたは 'ninjaFactory.FindAll()'メソッドを書くことができますか? – Kahbazi

+0

公開IEnumerable FindAll() { using(IDbConnection dbConnection = Connection) { dbConnection.Open(); return dbConnection.Query ( "SELECT * FROM ninjas"); } } – Jung

+0

これは、MVCまたはビューバックとは関係ありません。エラーメッセージは、何が間違っているかを説明します。 'Dojo'プロパティは少なくとも* nullです。 *表示するDojoがありますか?データはどのように見えますか? –

答えて

1

このコードの問題のカップルがあります。 Dojosはロードされておらず、あなたはRonins(dojos/mastersなしのninjas/samurais)を処理​​しません。

@perinearydevelopmentが説明しているように、Dapperはフル機能のORMのように自動的に関連するオブジェクトをロードしません。たとえば、JOINを使用して両方のオブジェクトを1行に戻し、別のフィールドに異なるオブジェクトをマップするにはmulti-mappingを使用する必要があります。

あなたが書くことができます。

var sql ="SELECT * FROM ninjas inner join Dojos on Ninjas.DojoID=Docos.ID"; 
dbConnection.Query<Ninja, Dojo, Ninja>(sql, (ninja, dojo) => 
    { 
     ninja.Dojo = dojo; 
     return ninja; 
    }); 

アンより良いオプションは、例えば、道場で忍者を返しビューを作成し、それにマッピングするために、次のようになります。

var sql ="SELECT * FROM ninjasWithDojos ..."; 
dbConnection.Query<Ninja, Dojo, Ninja>(sql, (ninja, dojo) => 
    { 
     ninja.Dojo = dojo; 
     return ninja; 
    }); 

他の部分の問題は、忍者がのDojoを持っていない可能性があるということです。内部結合を使用する場合、そのようなエントリをロードすることさえできません。あなたは左外部結合を使用してRoninsを読み込むことができます。

var sql ="SELECT * FROM ninjas left outer join Dojos on Ninjas.DojoID=Docos.ID"; 

あなたはヌルを無視するようにMVCビューのループを変更する必要があり、この場合。あなたは道場をチェックして、完全に、ヘッダを削除するか、別のスニペットレンダリングすることができます:私は代わりにViewBagModelを使用

@foreach(var ninja in Model.Ninja) 
{ 
    <h2>@ninja.Name</h2> 
    @if (ninja.Dojo != null) 
    {  
     <h4>@(ninja?.Dojo?.Name)??"Ronin!"</h4> 
    } 
} 

お知らせ。強く型付けされたビューを作成してデバッグする方がずっと簡単です。あなたのコントローラから直接忍者を返すことができます。

//Controller 
var ninjas= ninjaFactory.FindAll(); 
return View(ninjas); 

//View 
@model IEnumerable<Ninja> 


@foreach(var ninja in Model) 

かのViewModelクラスの一部として:

var ninjas= ninjaFactory.FindAll(); 
var villains = ...; 
var game = new GameModel { Ninjas = ninjas, Villains = villains}; 
return View(game); 

//View 
@model GameModel 


@foreach(var ninja in Model.Ninjas) 
1

documentationによると、あなたがこれにクエリを更新する必要があると思われる: var sql = @"select * from #Ninjas n left join #Dojos d on d.Id = n.DojoId Order by n.Id";

return dbConnection.Query<Post, Dojo>(sql, (ninja, dojo)=> { ninja.Dojo = dojo; return ninja;});

+1

文書では、結合で 'Dojos'を返す必要があると言います。 –

+0

@PanagiotisKanavosはい、実際のSQLクエリを含めるのを忘れました。更新しました、ありがとう! – peinearydevelopment

関連する問題