我有两个模特(Ninja& Dojo)。
他们是一对多的关系(忍者属于One Dojo,而Dojo可以拥有许多Ninjas)。
我正在使用Dapper。
Ninja.cs
public IEnumerable<Ninja> FindAll()
{
using (IDbConnection dbConnection = Connection)
{
dbConnection.Open();
return dbConnection.Query<Ninja>("SELECT * FROM ninjas");
}
}
Ninjafactory:
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; }
}
}
Dojo.cs
ninjaFactory.Add(newNinja, dojo);
System.Console.WriteLine(newNinja.Dojo.Name);
ViewBag.Ninja = ninjaFactory.FindAll();
return View();
在我的控制器中,
我有:
@{
foreach(var ninja in ViewBag.Ninja){
<h2>@ninja.Name</h2>
<h4>@ninja.Dojo.Name</h4>
}
}
现在,System.Console.WriteLine(newNinja.Dojo.Name)在控制台中正确打印出Dojo的名称。
但是,它不会在我的网络浏览器上显示Dojo的名称。
在我的cshtml中,
function myonFormSubmit(e)
{
var ts=e.values[0];
runQuery("INSERT INTO `TABLENAME` (`timestamp`,....) VALUES ('ts')");
}
function runQuery(qry)//This is pretty bare bones as it has no error handling built in. I removed it from a much more complicated function. Which you can find in the link in the text below.
{
var address='address';
var user='user';
var userPwd='pass';
var db='db';
var dbUrl='jdbc:mysql://' + address + '/' + db;
var conn=Jdbc.getConnection(dbUrl, user, userPwd);
var stmt=conn.prepareStatement(qry)
stmt.execute();
}
它确实打印出@ ninja.Name但它没有打印出@ ninja.Dojo.Name说
RuntimeBinderException:无法对空引用执行运行时绑定
如何使用ViewBag创建属于Ninja类的Dojo类的属性?
提前非常感谢你。
答案 0 :(得分: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 :(得分:1)
此代码存在一些问题。 Dojos没有装,你不会处理Ronins(没有Dojos / masters的忍者/武士)。
正如@peinearydevelopment所解释的那样,Dapper并不像自己的全功能ORM那样自动加载相关对象。您必须在一行中返回两个对象,例如使用JOIN并使用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;
});
更好的选择是创建一个 View ,它返回带有Dojos的Ninjas,并映射到它,例如:
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 View循环以忽略空值。您可以检查Dojo并完全删除标题,或者呈现不同的代码段:
@foreach(var ninja in Model.Ninja)
{
<h2>@ninja.Name</h2>
@if (ninja.Dojo != null)
{
<h4>@(ninja?.Dojo?.Name)??"Ronin!"</h4>
}
}
请注意,我使用Model
代替ViewBag
。编写和调试强类型视图要容易得多。您可以直接从控制器返回忍者:
//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)